From b04f8ed5325f2fe80c4a4577c39f5d535a45d041 Mon Sep 17 00:00:00 2001 From: John Goerzen Date: Tue, 21 Jun 2005 13:57:03 +0000 Subject: [PATCH] Import upstream gpsbabel version 1.2.5+1.2.6-beta20050608 --- Makefile | 258 ++-- README | 290 +++-- an1.c | 835 ++++++++++++ an1sym.h | 519 ++++++++ arcdist.c | 7 +- brauniger_iq.c | 1 + cetus.c | 17 +- chkdoc | 23 +- coastexp.c | 637 +++++++++ coldsync/pdb.c | 32 +- coldsync/util.c | 16 +- copilot.c | 5 +- csv_util.c | 130 +- csv_util.h | 3 + defs.h | 117 +- delgpl.c | 4 +- duplicate.c | 4 +- easygps.c | 3 +- filter_vecs.c | 17 +- garmin.c | 92 +- garmin_tables.c | 74 +- gbtypes.h | 48 + gcdb.c | 3 +- geo.c | 224 +--- geoniche.c | 9 +- glogbook.c | 180 +++ google.c | 213 +++ gpilots.c | 54 +- gpspilot.c | 5 +- gpsutil.c | 5 +- gpx.c | 229 ++-- gpxval | 32 +- hiketech.c | 281 ++++ holux.c | 3 +- hsa_ndv.c | 6 +- html.c | 17 +- igc.c | 11 +- ...Babel Windows GUI 2.00.00 Project Plan.pdf | Bin 0 -> 68640 bytes intdoc/SA2003_an1_dump.pl | 200 +++ internal_styles.c | 41 +- jeeps/gps.h | 5 +- jeeps/gpsapp.c | 280 ++-- jeeps/gpscom.c | 4 +- jeeps/gpscom.h | 4 +- jeeps/gpsinput.c | 15 +- jeeps/gpslibusb.c | 131 +- jeeps/gpsmem.c | 4 +- jeeps/gpsport.h | 21 +- jeeps/gpsprot.c | 2 +- jeeps/gpsprot.h | 3 +- jeeps/gpsread.c | 1 + jeeps/gpsread.h | 1 + jeeps/gpssend.c | 5 +- jeeps/gpsserial.c | 56 +- jeeps/gpsserial.h | 1 + jeeps/gpsusbint.h | 27 + jeeps/gpsusbread.c | 7 +- jeeps/gpsusbsend.c | 46 +- jeeps/gpsusbwin.c | 23 +- kml.c | 313 +++++ lowranceusr.c | 389 ++++++ macgpsbabel/Credits.rtf | 21 +- .../English.lproj/MainMenu.nib/objects.nib | Bin 22015 -> 22092 bytes macgpsbabel/MacGPSBabel.applescript | 278 +++- .../MacGPSBabel.pbproj/project.pbxproj | 4 +- magellan.h | 5 +- maggeo.c | 239 ++++ magnav.c | 9 +- magproto.c | 91 +- main.c | 18 +- make-an1sym.pl | 361 ++++++ mapopolis.c | 7 +- mapsend.c | 43 +- mapsource.c | 53 +- mingw/Makefile | 16 +- mingw/wintesto.cmd | 165 ++- mkshort.c | 110 +- msvc/GPSBabel.dsp | 111 +- msvc/GPSBabel.vcproj | 67 +- navicache.c | 1 + netstumbler.c | 1 + nmea.c | 4 +- overlay.c | 701 ++++++++++ ozi.c | 12 +- palmdoc.c | 32 +- pathaway.c | 631 +++++++++ pcx.c | 5 +- position.c | 32 +- psitrex.c | 19 +- psp.c | 7 +- queue.h | 13 +- quovadis.c | 11 +- reference/Glad_5.exp | 398 +++--- reference/an1-an1.ref | Bin 0 -> 2958 bytes reference/an1-in.ref | 26 + reference/an1-line-out.ref | Bin 0 -> 1848 bytes reference/an1-out.ref | Bin 0 -> 280 bytes reference/coastexp.nob | 370 ++++++ reference/coastexp.ref | 221 ++++ reference/coastexp.ref2 | 171 +++ reference/coastexp.ref3 | 238 ++++ reference/coastexp.ref4 | 156 +++ reference/foo.an1 | Bin 0 -> 135252 bytes reference/google.arc | 111 ++ reference/google.js | 2 + reference/google.xml | 1 + reference/googmap.sh | 5 + reference/googmapjs.sh | 5 + reference/hsandv.exp | 36 +- reference/igc1.gpx | 42 +- reference/igc1_3d.out | 2 +- reference/igc1_gpx.out | 50 +- reference/igc1_igc.out | 2 +- reference/igc2_gpx.out | 104 +- reference/lowrance.usr | Bin 0 -> 353 bytes reference/ov2-arc-out.ref | Bin 0 -> 2535 bytes reference/ov2-geo-out.ref | Bin 0 -> 416 bytes reference/ov2-in.ref | 9 + reference/pathaway-geo.loc | 38 + reference/route/route.gpx | 2 +- reference/route/tef_xml.mps | Bin 0 -> 12934 bytes reference/route/tef_xml.sample.xml | 2 + reference/track/TrkDB-GPil.pdb | Bin 0 -> 9544 bytes reference/track/pathaway.mps | Bin 0 -> 15468 bytes reference/track/pathaway.pdb | Bin 0 -> 44188 bytes reference/track/tef_xml.sample.xml | 2 + route.c | 10 + saroute.c | 11 +- shape.c | 13 +- stackfilter.c | 33 +- style/README.style | 27 + style/csv.style | 10 +- style/s_and_t.style | 11 +- style/saplus.style | 2 +- style/tabsep.style | 2 + style/xmap.style | 12 +- style/xmapwpt.style | 4 +- tef_xml.c | 308 +++++ testo | 113 +- text.c | 9 +- tiger.c | 3 +- tmpro.c | 5 +- tomtom.c | 343 +++++ tools/memdebug | 3 + tools/mkchanges | 1 + tpg.c | 6 +- util.c | 68 +- uuid.c | 37 + uuid.h | 22 + vcf.c | 140 ++ vecs.c | 205 ++- waypt.c | 21 +- win32/GPSBabelGUI.exe | Bin 0 -> 495104 bytes win32/README | 5 - win32/gpsbabelfront.dpr | 14 - win32/gpsbabelfront.exe | Bin 430080 -> 0 bytes win32/gpsbabelfront_mainform.dfm | 156 --- win32/gpsbabelfront_mainform.pas | 384 ------ win32/gui/AboutDialogU.ddp | Bin 0 -> 51 bytes win32/gui/AboutDialogU.dfm | 1151 +++++++++++++++++ win32/gui/AboutDialogU.pas | 67 + win32/gui/GPSBabelGUI.cfg | 38 + win32/gui/GPSBabelGUI.dof | 137 ++ win32/gui/GPSBabelGUI.dpr | 17 + win32/gui/GPSBabelGUI.ico | Bin 0 -> 766 bytes win32/gui/GPSBabelGUI.res | Bin 0 -> 1780 bytes win32/gui/GPSBabelGUI.todo | 28 + win32/gui/GPSBabelGUIDialogU.ddp | Bin 0 -> 51 bytes win32/gui/GPSBabelGUIDialogU.dfm | 218 ++++ win32/gui/GPSBabelGUIDialogU.pas | 480 +++++++ win32/gui/README.txt | 4 + win32/gui/VersionInfo.pas | 99 ++ win32/gui/filelist.txt | 17 + xcsv.c | 14 +- xmlgeneric.c | 269 ++++ xmlgeneric.h | 60 + 176 files changed, 13585 insertions(+), 2035 deletions(-) create mode 100644 an1.c create mode 100644 an1sym.h create mode 100644 coastexp.c create mode 100644 gbtypes.h create mode 100644 glogbook.c create mode 100644 google.c create mode 100644 hiketech.c create mode 100644 intdoc/GPSBabel Windows GUI 2.00.00 Project Plan.pdf create mode 100644 intdoc/SA2003_an1_dump.pl create mode 100644 jeeps/gpsusbint.h create mode 100644 kml.c create mode 100644 lowranceusr.c create mode 100644 maggeo.c create mode 100644 make-an1sym.pl create mode 100644 overlay.c create mode 100644 pathaway.c create mode 100644 reference/an1-an1.ref create mode 100644 reference/an1-in.ref create mode 100644 reference/an1-line-out.ref create mode 100644 reference/an1-out.ref create mode 100644 reference/coastexp.nob create mode 100644 reference/coastexp.ref create mode 100644 reference/coastexp.ref2 create mode 100644 reference/coastexp.ref3 create mode 100644 reference/coastexp.ref4 create mode 100644 reference/foo.an1 create mode 100644 reference/google.arc create mode 100644 reference/google.js create mode 100644 reference/google.xml create mode 100644 reference/googmap.sh create mode 100644 reference/googmapjs.sh create mode 100644 reference/lowrance.usr create mode 100644 reference/ov2-arc-out.ref create mode 100644 reference/ov2-geo-out.ref create mode 100644 reference/ov2-in.ref create mode 100644 reference/pathaway-geo.loc create mode 100644 reference/route/tef_xml.mps create mode 100644 reference/route/tef_xml.sample.xml create mode 100644 reference/track/TrkDB-GPil.pdb create mode 100644 reference/track/pathaway.mps create mode 100644 reference/track/pathaway.pdb create mode 100644 reference/track/tef_xml.sample.xml create mode 100644 tef_xml.c create mode 100644 tomtom.c create mode 100644 uuid.c create mode 100644 uuid.h create mode 100644 vcf.c create mode 100644 win32/GPSBabelGUI.exe delete mode 100644 win32/README delete mode 100644 win32/gpsbabelfront.dpr delete mode 100644 win32/gpsbabelfront.exe delete mode 100644 win32/gpsbabelfront_mainform.dfm delete mode 100644 win32/gpsbabelfront_mainform.pas create mode 100644 win32/gui/AboutDialogU.ddp create mode 100644 win32/gui/AboutDialogU.dfm create mode 100644 win32/gui/AboutDialogU.pas create mode 100644 win32/gui/GPSBabelGUI.cfg create mode 100644 win32/gui/GPSBabelGUI.dof create mode 100644 win32/gui/GPSBabelGUI.dpr create mode 100644 win32/gui/GPSBabelGUI.ico create mode 100644 win32/gui/GPSBabelGUI.res create mode 100644 win32/gui/GPSBabelGUI.todo create mode 100644 win32/gui/GPSBabelGUIDialogU.ddp create mode 100644 win32/gui/GPSBabelGUIDialogU.dfm create mode 100644 win32/gui/GPSBabelGUIDialogU.pas create mode 100644 win32/gui/README.txt create mode 100644 win32/gui/VersionInfo.pas create mode 100644 win32/gui/filelist.txt create mode 100644 xmlgeneric.c create mode 100644 xmlgeneric.h diff --git a/Makefile b/Makefile index 35ac1039a..733986566 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,8 @@ LIBEXPAT=-lexpat # -lefence # USB may required non-standard libraries (like libusb) be installed # and may not be available on all OSes. Uncomment this to remove the key # parts of USB from the build. -INHIBIT_USB=-DNO_USB +INHIBIT_USB=#-DNO_USB +LIBUSB=-lusb # # Enable either or both of these as you wish. @@ -25,7 +26,9 @@ FMTS=magproto.o gpx.o geo.o mapsend.o mapsource.o garmin_tables.o \ xcsv.o gcdb.o tiger.o internal_styles.o easygps.o quovadis.o \ gpilots.o saroute.o navicache.o psitrex.o geoniche.o delgpl.o \ ozi.o nmea.o text.o html.o palmdoc.o netstumbler.o hsa_ndv.o \ - igc.o brauniger_iq.o shape.o + igc.o brauniger_iq.o shape.o hiketech.o glogbook.o coastexp.o \ + vcf.o overlay.o kml.o google.o lowranceusr.o an1.o tomtom.o \ + tef_xml.o maggeo.o pathaway.o FILTERS=position.o duplicate.o arcdist.o polygon.o smplrout.o reverse_route.o sort.o stackfilter.o @@ -44,7 +47,7 @@ COLDSYNC=coldsync/util.o coldsync/pdb.o SHAPE=shapelib/shpopen.o shapelib/dbfopen.o LIBOBJS = queue.o route.o waypt.o filter_vecs.o util.o vecs.o mkshort.o \ - csv_util.o grtcirc.o vmem.o util_crc.o \ + csv_util.o grtcirc.o vmem.o util_crc.o xmlgeneric.o uuid.o \ $(COLDSYNC) $(GARMIN) $(JEEPS) $(SHAPE) $(FMTS) $(FILTERS) OBJS = main.o $(LIBOBJS) @@ -54,7 +57,7 @@ OBJS = main.o $(LIBOBJS) all: gpsbabel gpsbabel: $(OBJS) - $(CC) $(CFLAGS) $(OBJS) -o gpsbabel $(LIBEXPAT) -lm + $(CC) $(CFLAGS) $(OBJS) -o gpsbabel $(LIBEXPAT) $(LIBUSB) -lm main.o: $(CC) -c $(CFLAGS) -DVERSION=\"$(VERSIOND)\" $< @@ -88,10 +91,10 @@ dep: (echo -n "internal_styles.c: mkstyle.sh " ; echo style/*.style ; /bin/echo -e '\t./mkstyle.sh > internal_styles.c || (rm -f internal_styles.c ; exit 1)' ) >> /tmp/dep echo Edit Makefile and bring in /tmp/dep -#VERSIONU=1_2_4_beta10162004 -#VERSIOND=1.2.4_beta10162004 -VERSIONU=1_2_4 -VERSIOND=1.2.4 +VERSIONU=1_2_6-beta06082005 +VERSIOND=1.2.6_beta06082005 +# VERSIONU=1_2_5 +# VERSIOND=1.2.5 release: cvs commit @@ -107,8 +110,11 @@ release: curl -u anonymous:anonymous --upload-file /tmp/gpsbabel-$(VERSIOND).tar.gz ftp://upload.sf.net/incoming/ curl -u anonymous:anonymous --upload-file /tmp/gpsbabel-$(VERSIOND).zip ftp://upload.sf.net/incoming/ +mac-usbfree: + make LIBEXPAT=/sw/lib/libexpat.a EXTRA_CFLAGS="-I/sw/include" LIBUSB= INHIBIT_USB=-DNO_USB + mac-build: - make LIBEXPAT=/sw/lib/libexpat.a EXTRA_CFLAGS="-I/sw/include" + make LIBEXPAT=/sw/lib/libexpat.a EXTRA_CFLAGS="-I/sw/include" LIBUSB="/sw/lib/libusb.a -lIOKit -lBSDPClient -framework CoreFoundation" mac-release: mkdir -p usr/bin usr/share/gpsbabel/doc @@ -119,165 +125,197 @@ mac-release: # Machine generated from here down. -arcdist.o: arcdist.c defs.h queue.h grtcirc.h -brauniger_iq.o: brauniger_iq.c defs.h queue.h jeeps/gpsserial.h \ +an1.o: an1.c defs.h queue.h gbtypes.h an1sym.h +arcdist.o: arcdist.c defs.h queue.h gbtypes.h grtcirc.h +brauniger_iq.o: brauniger_iq.c defs.h queue.h gbtypes.h jeeps/gpsserial.h \ jeeps/gps.h jeeps/gpsport.h jeeps/gpssend.h jeeps/gpsread.h \ jeeps/gpsutil.h jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h \ jeeps/gpsfmt.h jeeps/gpsmath.h jeeps/gpsnmea.h jeeps/gpsmem.h \ jeeps/gpsrqst.h jeeps/gpsinput.h jeeps/gpsproj.h jeeps/gpsnmeafmt.h \ jeeps/gpsnmeaget.h -cetus.o: cetus.c defs.h queue.h coldsync/palm.h coldsync/pdb.h -copilot.o: copilot.c defs.h queue.h coldsync/palm.h coldsync/pdb.h -csv_util.o: csv_util.c defs.h queue.h csv_util.h grtcirc.h -delgpl.o: delgpl.c defs.h queue.h -duplicate.o: duplicate.c defs.h queue.h -easygps.o: easygps.c defs.h queue.h -filter_vecs.o: filter_vecs.c defs.h queue.h -garmin.o: garmin.c defs.h queue.h jeeps/gps.h jeeps/gpsport.h \ +cetus.o: cetus.c defs.h queue.h gbtypes.h coldsync/palm.h coldsync/pdb.h +coastexp.o: coastexp.c defs.h queue.h gbtypes.h xmlgeneric.h uuid.h +copilot.o: copilot.c defs.h queue.h gbtypes.h coldsync/palm.h \ + coldsync/pdb.h +csv_util.o: csv_util.c defs.h queue.h gbtypes.h csv_util.h grtcirc.h +delgpl.o: delgpl.c defs.h queue.h gbtypes.h +duplicate.o: duplicate.c defs.h queue.h gbtypes.h +easygps.o: easygps.c defs.h queue.h gbtypes.h +filter_vecs.o: filter_vecs.c defs.h queue.h gbtypes.h +garmin.o: garmin.c defs.h queue.h gbtypes.h jeeps/gps.h jeeps/gpsport.h \ jeeps/gpsserial.h jeeps/gpssend.h jeeps/gpsread.h jeeps/gpsutil.h \ jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h jeeps/gpsfmt.h \ jeeps/gpsmath.h jeeps/gpsnmea.h jeeps/gpsmem.h jeeps/gpsrqst.h \ jeeps/gpsinput.h jeeps/gpsproj.h jeeps/gpsnmeafmt.h jeeps/gpsnmeaget.h \ garmin_tables.h garmin_tables.o: garmin_tables.c garmin_tables.h -gcdb.o: gcdb.c defs.h queue.h coldsync/palm.h coldsync/pdb.h -geo.o: geo.c defs.h queue.h -geoniche.o: geoniche.c defs.h queue.h coldsync/palm.h coldsync/pdb.h -gpilots.o: gpilots.c defs.h queue.h coldsync/palm.h coldsync/pdb.h \ - garmin_tables.h -gpspilot.o: gpspilot.c defs.h queue.h coldsync/palm.h coldsync/pdb.h -gpsutil.o: gpsutil.c defs.h queue.h magellan.h -gpx.o: gpx.c defs.h queue.h -grtcirc.o: grtcirc.c defs.h queue.h -holux.o: holux.c defs.h queue.h holux.h -hsa_ndv.o: hsa_ndv.c defs.h queue.h -html.o: html.c defs.h queue.h jeeps/gpsmath.h jeeps/gps.h jeeps/gpsport.h \ - jeeps/gpsserial.h jeeps/gpssend.h jeeps/gpsread.h jeeps/gpsutil.h \ - jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h jeeps/gpsfmt.h \ - jeeps/gpsnmea.h jeeps/gpsmem.h jeeps/gpsrqst.h jeeps/gpsinput.h \ - jeeps/gpsproj.h jeeps/gpsnmeafmt.h jeeps/gpsnmeaget.h -igc.o: igc.c defs.h queue.h -internal_styles.o: internal_styles.c defs.h queue.h -magnav.o: magnav.c defs.h queue.h coldsync/palm.h coldsync/pdb.h -magproto.o: magproto.c defs.h queue.h magellan.h -main.o: main.c defs.h queue.h -mapsend.o: mapsend.c defs.h queue.h mapsend.h magellan.h -mapsource.o: mapsource.c defs.h queue.h garmin_tables.h -mkshort.o: mkshort.c defs.h queue.h -navicache.o: navicache.c defs.h queue.h -netstumbler.o: netstumbler.c defs.h queue.h csv_util.h -nmea.o: nmea.c defs.h queue.h -ozi.o: ozi.c defs.h queue.h csv_util.h -palmdoc.o: palmdoc.c defs.h queue.h jeeps/gpsmath.h jeeps/gps.h \ +gcdb.o: gcdb.c defs.h queue.h gbtypes.h coldsync/palm.h coldsync/pdb.h +geo.o: geo.c defs.h queue.h gbtypes.h xmlgeneric.h +geoniche.o: geoniche.c defs.h queue.h gbtypes.h coldsync/palm.h \ + coldsync/pdb.h +glogbook.o: glogbook.c defs.h queue.h gbtypes.h xmlgeneric.h +google.o: google.c defs.h queue.h gbtypes.h xmlgeneric.h +gpilots.o: gpilots.c defs.h queue.h gbtypes.h coldsync/palm.h \ + coldsync/pdb.h garmin_tables.h +gpspilot.o: gpspilot.c defs.h queue.h gbtypes.h coldsync/palm.h \ + coldsync/pdb.h +gpsutil.o: gpsutil.c defs.h queue.h gbtypes.h magellan.h +gpx.o: gpx.c defs.h queue.h gbtypes.h xmlgeneric.h +grtcirc.o: grtcirc.c defs.h queue.h gbtypes.h +hiketech.o: hiketech.c defs.h queue.h gbtypes.h xmlgeneric.h +holux.o: holux.c defs.h queue.h gbtypes.h holux.h +hsa_ndv.o: hsa_ndv.c defs.h queue.h gbtypes.h +html.o: html.c defs.h queue.h gbtypes.h jeeps/gpsmath.h jeeps/gps.h \ + jeeps/gpsport.h jeeps/gpsserial.h jeeps/gpssend.h jeeps/gpsread.h \ + jeeps/gpsutil.h jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h \ + jeeps/gpsfmt.h jeeps/gpsnmea.h jeeps/gpsmem.h jeeps/gpsrqst.h \ + jeeps/gpsinput.h jeeps/gpsproj.h jeeps/gpsnmeafmt.h jeeps/gpsnmeaget.h +igc.o: igc.c defs.h queue.h gbtypes.h +internal_styles.o: internal_styles.c defs.h queue.h gbtypes.h +kml.o: kml.c defs.h queue.h gbtypes.h xmlgeneric.h +lowranceusr.o: lowranceusr.c defs.h queue.h gbtypes.h +magnav.o: magnav.c defs.h queue.h gbtypes.h coldsync/palm.h \ + coldsync/pdb.h +magproto.o: magproto.c defs.h queue.h gbtypes.h magellan.h +main.o: main.c defs.h queue.h gbtypes.h +tef_xml.o: tef_xml.c defs.h queue.h gbtypes.h xmlgeneric.h +pathaway.o: pathaway.c defs.h queue.h gbtypes.h \ + coldsync/palm.h coldsync/pdb.h csv_util.h +mapsend.o: mapsend.c defs.h queue.h gbtypes.h mapsend.h magellan.h +mapsource.o: mapsource.c defs.h queue.h gbtypes.h garmin_tables.h +mkshort.o: mkshort.c defs.h queue.h gbtypes.h +navicache.o: navicache.c defs.h queue.h gbtypes.h +netstumbler.o: netstumbler.c defs.h queue.h gbtypes.h csv_util.h +nmea.o: nmea.c defs.h queue.h gbtypes.h +overlay.o: overlay.c defs.h queue.h gbtypes.h grtcirc.h +ozi.o: ozi.c defs.h queue.h gbtypes.h csv_util.h +palmdoc.o: palmdoc.c defs.h queue.h gbtypes.h jeeps/gpsmath.h jeeps/gps.h \ jeeps/gpsport.h jeeps/gpsserial.h jeeps/gpssend.h jeeps/gpsread.h \ jeeps/gpsutil.h jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h \ jeeps/gpsfmt.h jeeps/gpsnmea.h jeeps/gpsmem.h jeeps/gpsrqst.h \ jeeps/gpsinput.h jeeps/gpsproj.h jeeps/gpsnmeafmt.h jeeps/gpsnmeaget.h \ coldsync/palm.h coldsync/pdb.h -pcx.o: pcx.c defs.h queue.h garmin_tables.h -polygon.o: polygon.c defs.h queue.h -position.o: position.c defs.h queue.h grtcirc.h -psitrex.o: psitrex.c defs.h queue.h garmin_tables.h -psp.o: psp.c defs.h queue.h +pcx.o: pcx.c defs.h queue.h gbtypes.h garmin_tables.h +polygon.o: polygon.c defs.h queue.h gbtypes.h +position.o: position.c defs.h queue.h gbtypes.h grtcirc.h +psitrex.o: psitrex.c defs.h queue.h gbtypes.h garmin_tables.h +psp.o: psp.c defs.h queue.h gbtypes.h queue.o: queue.c queue.h -quovadis.o: quovadis.c quovadis.h defs.h queue.h coldsync/palm.h \ - coldsync/pdb.h -reverse_route.o: reverse_route.c defs.h queue.h -route.o: route.c defs.h queue.h -saroute.o: saroute.c defs.h queue.h -shape.o: shape.c defs.h queue.h shapelib/shapefil.h -smplrout.o: smplrout.c defs.h queue.h grtcirc.h -sort.o: sort.c defs.h queue.h -stackfilter.o: stackfilter.c defs.h queue.h -text.o: text.c defs.h queue.h jeeps/gpsmath.h jeeps/gps.h jeeps/gpsport.h \ - jeeps/gpsserial.h jeeps/gpssend.h jeeps/gpsread.h jeeps/gpsutil.h \ - jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h jeeps/gpsfmt.h \ - jeeps/gpsnmea.h jeeps/gpsmem.h jeeps/gpsrqst.h jeeps/gpsinput.h \ - jeeps/gpsproj.h jeeps/gpsnmeafmt.h jeeps/gpsnmeaget.h -tiger.o: tiger.c defs.h queue.h csv_util.h -tmpro.o: tmpro.c defs.h queue.h csv_util.h -tpg.o: tpg.c defs.h queue.h jeeps/gpsmath.h jeeps/gps.h jeeps/gpsport.h \ - jeeps/gpsserial.h jeeps/gpssend.h jeeps/gpsread.h jeeps/gpsutil.h \ - jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h jeeps/gpsfmt.h \ - jeeps/gpsnmea.h jeeps/gpsmem.h jeeps/gpsrqst.h jeeps/gpsinput.h \ - jeeps/gpsproj.h jeeps/gpsnmeafmt.h jeeps/gpsnmeaget.h -util.o: util.c defs.h queue.h +quovadis.o: quovadis.c quovadis.h defs.h queue.h gbtypes.h \ + coldsync/palm.h coldsync/pdb.h +reverse_route.o: reverse_route.c defs.h queue.h gbtypes.h +route.o: route.c defs.h queue.h gbtypes.h +saroute.o: saroute.c defs.h queue.h gbtypes.h +shape.o: shape.c defs.h queue.h gbtypes.h shapelib/shapefil.h +smplrout.o: smplrout.c defs.h queue.h gbtypes.h grtcirc.h +sort.o: sort.c defs.h queue.h gbtypes.h +stackfilter.o: stackfilter.c defs.h queue.h gbtypes.h +text.o: text.c defs.h queue.h gbtypes.h jeeps/gpsmath.h jeeps/gps.h \ + jeeps/gpsport.h jeeps/gpsserial.h jeeps/gpssend.h jeeps/gpsread.h \ + jeeps/gpsutil.h jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h \ + jeeps/gpsfmt.h jeeps/gpsnmea.h jeeps/gpsmem.h jeeps/gpsrqst.h \ + jeeps/gpsinput.h jeeps/gpsproj.h jeeps/gpsnmeafmt.h jeeps/gpsnmeaget.h +tiger.o: tiger.c defs.h queue.h gbtypes.h csv_util.h +tmpro.o: tmpro.c defs.h queue.h gbtypes.h csv_util.h +tomtom.o: tomtom.c defs.h queue.h gbtypes.h +tpg.o: tpg.c defs.h queue.h gbtypes.h jeeps/gpsmath.h jeeps/gps.h \ + jeeps/gpsport.h jeeps/gpsserial.h jeeps/gpssend.h jeeps/gpsread.h \ + jeeps/gpsutil.h jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h \ + jeeps/gpsfmt.h jeeps/gpsnmea.h jeeps/gpsmem.h jeeps/gpsrqst.h \ + jeeps/gpsinput.h jeeps/gpsproj.h jeeps/gpsnmeafmt.h jeeps/gpsnmeaget.h +util.o: util.c defs.h queue.h gbtypes.h util_crc.o: util_crc.c -vecs.o: vecs.c defs.h queue.h csv_util.h -vmem.o: vmem.c defs.h queue.h -waypt.o: waypt.c defs.h queue.h -xcsv.o: xcsv.c defs.h queue.h csv_util.h +uuid.o: uuid.c uuid.h +vcf.o: vcf.c defs.h queue.h gbtypes.h jeeps/gpsmath.h jeeps/gps.h \ + jeeps/gpsport.h jeeps/gpsserial.h jeeps/gpssend.h jeeps/gpsread.h \ + jeeps/gpsutil.h jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h \ + jeeps/gpsfmt.h jeeps/gpsnmea.h jeeps/gpsmem.h jeeps/gpsrqst.h \ + jeeps/gpsinput.h jeeps/gpsproj.h jeeps/gpsnmeafmt.h jeeps/gpsnmeaget.h +vecs.o: vecs.c defs.h queue.h gbtypes.h csv_util.h +vmem.o: vmem.c defs.h queue.h gbtypes.h +waypt.o: waypt.c defs.h queue.h gbtypes.h +xcsv.o: xcsv.c defs.h queue.h gbtypes.h csv_util.h +xmlgeneric.o: xmlgeneric.c defs.h queue.h gbtypes.h xmlgeneric.h coldsync/pdb.o: coldsync/pdb.c coldsync/config.h coldsync/palm.h \ coldsync/pdb.h coldsync/util.o: coldsync/util.c coldsync/config.h coldsync/pconn/util.h \ coldsync/palm.h -jeeps/gpsapp.o: jeeps/gpsapp.c jeeps/gps.h defs.h queue.h jeeps/gpsport.h \ - jeeps/gpsserial.h jeeps/gpssend.h jeeps/gpsread.h jeeps/gpsutil.h \ - jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h jeeps/gpsfmt.h \ - jeeps/gpsmath.h jeeps/gpsnmea.h jeeps/gpsmem.h jeeps/gpsrqst.h \ - jeeps/gpsinput.h jeeps/gpsproj.h jeeps/gpsnmeafmt.h jeeps/gpsnmeaget.h -jeeps/gpscom.o: jeeps/gpscom.c jeeps/gps.h defs.h queue.h jeeps/gpsport.h \ - jeeps/gpsserial.h jeeps/gpssend.h jeeps/gpsread.h jeeps/gpsutil.h \ - jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h jeeps/gpsfmt.h \ - jeeps/gpsmath.h jeeps/gpsnmea.h jeeps/gpsmem.h jeeps/gpsrqst.h \ - jeeps/gpsinput.h jeeps/gpsproj.h jeeps/gpsnmeafmt.h jeeps/gpsnmeaget.h -jeeps/gpslibusb.o: jeeps/gpslibusb.c -jeeps/gpsmath.o: jeeps/gpsmath.c jeeps/gps.h defs.h queue.h \ +jeeps/gpsapp.o: jeeps/gpsapp.c jeeps/gps.h defs.h queue.h gbtypes.h \ jeeps/gpsport.h jeeps/gpsserial.h jeeps/gpssend.h jeeps/gpsread.h \ jeeps/gpsutil.h jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h \ jeeps/gpsfmt.h jeeps/gpsmath.h jeeps/gpsnmea.h jeeps/gpsmem.h \ jeeps/gpsrqst.h jeeps/gpsinput.h jeeps/gpsproj.h jeeps/gpsnmeafmt.h \ - jeeps/gpsnmeaget.h jeeps/gpsdatum.h -jeeps/gpsmem.o: jeeps/gpsmem.c jeeps/gps.h defs.h queue.h jeeps/gpsport.h \ - jeeps/gpsserial.h jeeps/gpssend.h jeeps/gpsread.h jeeps/gpsutil.h \ - jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h jeeps/gpsfmt.h \ - jeeps/gpsmath.h jeeps/gpsnmea.h jeeps/gpsmem.h jeeps/gpsrqst.h \ - jeeps/gpsinput.h jeeps/gpsproj.h jeeps/gpsnmeafmt.h jeeps/gpsnmeaget.h \ - jeeps/garminusb.h -jeeps/gpsprot.o: jeeps/gpsprot.c jeeps/gps.h defs.h queue.h \ + jeeps/gpsnmeaget.h +jeeps/gpscom.o: jeeps/gpscom.c jeeps/gps.h defs.h queue.h gbtypes.h \ jeeps/gpsport.h jeeps/gpsserial.h jeeps/gpssend.h jeeps/gpsread.h \ jeeps/gpsutil.h jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h \ jeeps/gpsfmt.h jeeps/gpsmath.h jeeps/gpsnmea.h jeeps/gpsmem.h \ jeeps/gpsrqst.h jeeps/gpsinput.h jeeps/gpsproj.h jeeps/gpsnmeafmt.h \ jeeps/gpsnmeaget.h -jeeps/gpsread.o: jeeps/gpsread.c jeeps/gps.h defs.h queue.h \ +jeeps/gpslibusb.o: jeeps/gpslibusb.c jeeps/gps.h defs.h queue.h gbtypes.h \ jeeps/gpsport.h jeeps/gpsserial.h jeeps/gpssend.h jeeps/gpsread.h \ jeeps/gpsutil.h jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h \ jeeps/gpsfmt.h jeeps/gpsmath.h jeeps/gpsnmea.h jeeps/gpsmem.h \ jeeps/gpsrqst.h jeeps/gpsinput.h jeeps/gpsproj.h jeeps/gpsnmeafmt.h \ - jeeps/gpsnmeaget.h -jeeps/gpsrqst.o: jeeps/gpsrqst.c jeeps/gps.h defs.h queue.h \ + jeeps/gpsnmeaget.h jeeps/garminusb.h +jeeps/gpsmath.o: jeeps/gpsmath.c jeeps/gps.h defs.h queue.h gbtypes.h \ jeeps/gpsport.h jeeps/gpsserial.h jeeps/gpssend.h jeeps/gpsread.h \ jeeps/gpsutil.h jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h \ jeeps/gpsfmt.h jeeps/gpsmath.h jeeps/gpsnmea.h jeeps/gpsmem.h \ jeeps/gpsrqst.h jeeps/gpsinput.h jeeps/gpsproj.h jeeps/gpsnmeafmt.h \ - jeeps/gpsnmeaget.h -jeeps/gpssend.o: jeeps/gpssend.c jeeps/gps.h defs.h queue.h \ + jeeps/gpsnmeaget.h jeeps/gpsdatum.h +jeeps/gpsmem.o: jeeps/gpsmem.c jeeps/gps.h defs.h queue.h gbtypes.h \ + jeeps/gpsport.h jeeps/gpsserial.h jeeps/gpssend.h jeeps/gpsread.h \ + jeeps/gpsutil.h jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h \ + jeeps/gpsfmt.h jeeps/gpsmath.h jeeps/gpsnmea.h jeeps/gpsmem.h \ + jeeps/gpsrqst.h jeeps/gpsinput.h jeeps/gpsproj.h jeeps/gpsnmeafmt.h \ + jeeps/gpsnmeaget.h jeeps/garminusb.h +jeeps/gpsprot.o: jeeps/gpsprot.c jeeps/gps.h defs.h queue.h gbtypes.h \ jeeps/gpsport.h jeeps/gpsserial.h jeeps/gpssend.h jeeps/gpsread.h \ jeeps/gpsutil.h jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h \ jeeps/gpsfmt.h jeeps/gpsmath.h jeeps/gpsnmea.h jeeps/gpsmem.h \ jeeps/gpsrqst.h jeeps/gpsinput.h jeeps/gpsproj.h jeeps/gpsnmeafmt.h \ jeeps/gpsnmeaget.h -jeeps/gpsserial.o: jeeps/gpsserial.c jeeps/gps.h defs.h queue.h \ +jeeps/gpsread.o: jeeps/gpsread.c jeeps/gps.h defs.h queue.h gbtypes.h \ + jeeps/gpsport.h jeeps/gpsserial.h jeeps/gpssend.h jeeps/gpsread.h \ + jeeps/gpsutil.h jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h \ + jeeps/gpsfmt.h jeeps/gpsmath.h jeeps/gpsnmea.h jeeps/gpsmem.h \ + jeeps/gpsrqst.h jeeps/gpsinput.h jeeps/gpsproj.h jeeps/gpsnmeafmt.h \ + jeeps/gpsnmeaget.h jeeps/gpsusbint.h +jeeps/gpsrqst.o: jeeps/gpsrqst.c jeeps/gps.h defs.h queue.h gbtypes.h \ jeeps/gpsport.h jeeps/gpsserial.h jeeps/gpssend.h jeeps/gpsread.h \ jeeps/gpsutil.h jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h \ jeeps/gpsfmt.h jeeps/gpsmath.h jeeps/gpsnmea.h jeeps/gpsmem.h \ jeeps/gpsrqst.h jeeps/gpsinput.h jeeps/gpsproj.h jeeps/gpsnmeafmt.h \ jeeps/gpsnmeaget.h -jeeps/gpsusbread.o: jeeps/gpsusbread.c jeeps/gps.h defs.h queue.h \ +jeeps/gpssend.o: jeeps/gpssend.c jeeps/gps.h defs.h queue.h gbtypes.h \ jeeps/gpsport.h jeeps/gpsserial.h jeeps/gpssend.h jeeps/gpsread.h \ jeeps/gpsutil.h jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h \ jeeps/gpsfmt.h jeeps/gpsmath.h jeeps/gpsnmea.h jeeps/gpsmem.h \ jeeps/gpsrqst.h jeeps/gpsinput.h jeeps/gpsproj.h jeeps/gpsnmeafmt.h \ - jeeps/gpsnmeaget.h jeeps/garminusb.h -jeeps/gpsusbsend.o: jeeps/gpsusbsend.c jeeps/gps.h defs.h queue.h \ + jeeps/gpsnmeaget.h jeeps/gpsusbint.h +jeeps/gpsserial.o: jeeps/gpsserial.c jeeps/gps.h defs.h queue.h gbtypes.h \ jeeps/gpsport.h jeeps/gpsserial.h jeeps/gpssend.h jeeps/gpsread.h \ jeeps/gpsutil.h jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h \ jeeps/gpsfmt.h jeeps/gpsmath.h jeeps/gpsnmea.h jeeps/gpsmem.h \ jeeps/gpsrqst.h jeeps/gpsinput.h jeeps/gpsproj.h jeeps/gpsnmeafmt.h \ jeeps/gpsnmeaget.h jeeps/garminusb.h -jeeps/gpsusbstub.o: jeeps/gpsusbstub.c jeeps/garminusb.h -jeeps/gpsutil.o: jeeps/gpsutil.c jeeps/gps.h defs.h queue.h \ +jeeps/gpsusbread.o: jeeps/gpsusbread.c jeeps/gps.h defs.h queue.h \ + gbtypes.h jeeps/gpsport.h jeeps/gpsserial.h jeeps/gpssend.h \ + jeeps/gpsread.h jeeps/gpsutil.h jeeps/gpsapp.h jeeps/gpsprot.h \ + jeeps/gpscom.h jeeps/gpsfmt.h jeeps/gpsmath.h jeeps/gpsnmea.h \ + jeeps/gpsmem.h jeeps/gpsrqst.h jeeps/gpsinput.h jeeps/gpsproj.h \ + jeeps/gpsnmeafmt.h jeeps/gpsnmeaget.h jeeps/garminusb.h \ + jeeps/gpsusbint.h +jeeps/gpsusbsend.o: jeeps/gpsusbsend.c jeeps/gps.h defs.h queue.h \ + gbtypes.h jeeps/gpsport.h jeeps/gpsserial.h jeeps/gpssend.h \ + jeeps/gpsread.h jeeps/gpsutil.h jeeps/gpsapp.h jeeps/gpsprot.h \ + jeeps/gpscom.h jeeps/gpsfmt.h jeeps/gpsmath.h jeeps/gpsnmea.h \ + jeeps/gpsmem.h jeeps/gpsrqst.h jeeps/gpsinput.h jeeps/gpsproj.h \ + jeeps/gpsnmeafmt.h jeeps/gpsnmeaget.h jeeps/garminusb.h \ + jeeps/gpsusbint.h +jeeps/gpsusbstub.o: jeeps/gpsusbstub.c +jeeps/gpsutil.o: jeeps/gpsutil.c jeeps/gps.h defs.h queue.h gbtypes.h \ jeeps/gpsport.h jeeps/gpsserial.h jeeps/gpssend.h jeeps/gpsread.h \ jeeps/gpsutil.h jeeps/gpsapp.h jeeps/gpsprot.h jeeps/gpscom.h \ jeeps/gpsfmt.h jeeps/gpsmath.h jeeps/gpsnmea.h jeeps/gpsmem.h \ diff --git a/README b/README index bd6cf7ac5..164cb44fa 100644 --- a/README +++ b/README @@ -1,12 +1,12 @@ THE PROBLEM - There are simply too many gratituosuly different file formats to + There are simply too many gratuitously different file formats to hold waypoint, track, and route information in various programs used by computers. GPX (http://www.topografix.com/gpx.asp) - attempts to define a standard in XML to contain all the data, - but there are too many programs that don't understand it yet and - too much data that are in an alternate format. + defines a standard in XML to contain all the data, but there + are too many programs that don't understand it yet and + too much data that are in an alternate formats. THE SOLUTION @@ -37,6 +37,79 @@ GETTING IT / BUILDING IT Exapt can be downloaded from http://expat.sourceforge.net and is part of Apache so it's very portable. +COMMON USAGE + + Invocation was meant to be flexible. Unfortunately, that can + sometimes lead to unwieldy command lines. + + gpsbabel -? + + will always show you the supported file types. To use this + program, just tell it what you're reading, where to read it from, + what you're writing, and what to write it to. For example: + + gpsbabel -i geo -f /tmp/geocaching.loc -o gpx -F /tmp/geocaching.gpx + + tells it to read the first file in geocaching.com format and create + a new file in GPX format. + + This command will read from a Magellan unit attached to the first + serial port on a Linux system (device names will vary on other OSes) + and write them as a geocaching loc file. The second command does + the same for windows. + + gpsbabel -i magellan -f /dev/ttyS0 -o geo -F mag.loc + gpsbabel -i magellan -f com1 -o geo -F mag.loc + + PathAway (Palm) database + + PathAway is a Palm software designed for handling "most" GPS devices + (including BlueTooth). In this time (i mean 2005) a free tool + to convert this database is located on the homepage + of PathAway (www.pathaway.com). But i've read there ... for windows and + the output format was also very limited. + + Optionally, you may specify "-s" in any command line. This causes + the program to ignore any "short" names that may be present in the + source data format and synthesize one from the long name. This + is particularly useful if you're writing to a target format that + isn't the lowest common denominator but the source data was written + for the lowest common denominator. I use this for writing data + from geocaching.com to my Magellan so my waypoints have "real" names + instead of the 'GC1234' ones that are optimized for NMEA-only + receivers. A geocacher with a Magellan receiver may thus find + commands like this useful. + + gpsbabel -s -i geo -f geocaching.loc -o magellan -F /dev/ttyS0 + gpsbabel -s -i geo -f geocaching.loc -o magellan -F com1 + +ADVANCED USAGE + + Argument are processed in the order they appear on the command line. + Input is cumulative. The input file type remains unchanged until a + new -i argument is seen. Files are read in the order they appear. + So you could merge three input files into one output file with: + + gpsbabel -i geo -f 1.loc -f 2.loc -f 3.loc -o geo -F big.loc + + You can merge files of different types: + + gpsbabel -i geo -f 1.loc -i gpx -f 2.gpx -i pcx 3.pcx -o gpsutil -F big.gps + + You can write the same data in different output formats: + + gpsbabel -i geo -f 1.loc -o gpx -F 1.gpx -o pcx 1.wpt + +ROUTE AND TRACK MODES + + The presence of "-t" on the command line tells us to work with + tracks. The presence of "-r" tells us to work with routes. + Tracks and routes are advanced features and don't try to + handle every possible hazard that can be encountered during a + conversion. If you're merging or converting files of similar + limitations, things work very well. The presence of "-s" on + the command line tends to creat havoc because tracks and routes. + THE FORMATS GPX @@ -68,6 +141,15 @@ THE FORMATS Additional sub options: baud: may be 1200, 2400, 4800, 9600, 19200, but must match receiver. + MAGELLANX + + The SD card format used by the Magellan Explorist 300, 400, and 500. + It's identical to the Magellan SD format used by Meridian, but allows + longer waypoint names. + + You should name any file created with this format with a ".upt" + extension so the firmware can read it. + GARMIN Waypoint serial upload and download works reliably under both @@ -102,8 +184,6 @@ THE FORMATS dumps by adding "-D9" to the command line, like: gpsbabel -D9 -i garmin -f usb: -o gpx -F blah.gpx - - GPSMAN @@ -131,10 +211,18 @@ THE FORMATS is the one that makes Delorme S&A Deluxe 9 happy. It's also a very simple program and useful for many other programs like spreadsheets. - CSV is also the correct format for Lowrance MapCreate, their - commercial mapping program, or GDM6 (their free waypoint - manager) for iFinder which is available at - http://www.lowrance.com/Software/GDM6/Default.asp + CSV is also the correct format for Lowrance MapCreate, + their commercial mapping program, or GDM6 (their free + waypoint manager) for iFinder which is available at + http://www.lowrance.com/Software/GDM6/Default.asp + + LowranceUSR + + The Lowrance iFinder GPS series has the unique capability to + output its data to an MMC card. The data is saved to the card + as a .USR file and can be read by your computer using a card + reader. Currently only reading and writing of waypoints (no + routes or tracks) is supported. XMap @@ -473,6 +561,13 @@ THE FORMATS http://www.navicache.com/cgi-bin/ib312a/ikonboard.cgi?act=ST;f=23;t=334 + coastexp + + This is the format used by CoastalExplorer (tm). The format is + XML with items uniquely identified by Windows-style UUIDs. + + http://www.rosepointnav.com + PsiTrex This is a text format created by KuDaTa's PsiTrex program for the Psion @@ -640,7 +735,109 @@ THE FORMATS HSA Systems Endeavour Navigator format - will import both the old version 4.x binary files, and the newer XML based ones. - Only writes the new XML (5.0 and above) format. (use the .exp extension) + Only writes the new XML (5.0 and above) format. (use the .exp + extension) + + vCARD + + The vCard output is intended to be in a format that enables + waypoints to be viewed with an Apple iPod. This is achieved by + mapping waypoint fields into vCard fields that can be displayed + as 'Contacts' on the iPod. With the iPod mounted as a hard disk + (see your iPod manual for instructions), the resulting VCF + file should be moved into the iPod 'Contacts' folder. As an + alternative, Mac OS X users may prefer to drag the VCF file into + their address book and synchronize with the iPod using iSync. By + default hints are unencrypted; use the 'encrypt' option to + encrypt the hints. + + Hiketech + + This is the .gps format used by the Mac OS X applications + written by HikeTech. These include TopoDraw, Link2GPS, and + GPSWrite. More information about these products can be found at + http://www.hiketech.com + + glogbook + + This is the XML format used by the Garmin Logbook product that + ships with Forerunner and Foretrex. + + http://www.garmin.com + + KML + + We have sketchy support for KML, the Keyhole Markup Language. + There are many features in this file format that we don't yet + support, but simple waypoint lists convert fine. + + GOOGLE + + This format is designed to read the XML emitted when you tack + "&output=js" onto the end of a Google Maps route URL (use the + "link to this page" option to get a usable URL.) This allows + you to plan a route using Google Maps, then download it and use + it in your own mapping program or GPS receiver. If you use a + Unix-compatible operating system, this shell script might be + useful: + + #!/bin/sh + FROM="233 S. Wacker, Chicago, IL" + TO="1060 W. Addison, Chicago, IL" + wget -O - "http://maps.google.com/maps?q=$FROM to $TO&output=js" \ + 2>/dev/null >google_map.js + + gpsbabel -i google -f google_map.js -o gpx -F google_map.gpx + + TourExchangeFormat + + XML based export format, used by Map&Guide + "Motorrad-Routenplaner". This software can only export routing data. + So we don't support writing. + + PathAway + + PathAway is a Palm software designed for handling "most" GPS devices + (including BlueTooth). In this time (i mean 2005) a free tool + to convert this database is located on the homepage + of PathAway (www.pathaway.com). But i've read there ... for windows and + the output formats are also very limited. + + AN1 + + This format supports the DeLorme ".an1" drawing file format. It + can currently be used to either read or write drawing files. If + you use this format to create drawing files with routes or waypoints + from another source, it will currently create "Red Flag" symbols + for waypoints, and thick red lines for routes or tracks. It is + possible to merge two drawing layers by doing something like this: + + gpsbabel -i an1 -f one.an1 -f two.an1 -o an1 -F merged.an1 + + In this case, the merged data will contain all of the properties + of the original data. + + Currently, GPSBabel only writes drawing layers, as opposed to road, + track, and other specialized layers. If your input file is a road, + track, trail, or waypoint layer, you should not attempt to write to + an .an1 file as the results may be unpredictable. Note that this + also applies to merging files, so you can't currently merge two road + layers with GPSBabel (officially; there is an unsupported "type" + option that works in limited cases.) + + TomTom + + This format can read and write TomTom .ov2 (POI) files, as used by the + TomTom GO and TomTom Navigator. It has been tested with an original + TomTom GO running version 5.00 of the TomTom software. There may be + some records that confuse the input module - if you have an example + of such a record "in the wild", and you aren't restricted from sharing + it, we encourage you to post to the gpsbabel-misc mailing list to + contact a developer. + + Note that in addition to the .ov2 file, you will need a .bmp file for + the icon. It should be 22x22 and 16 colors, and have the same name + (not including the extension) as the .ov2 file. DATA FILTERS @@ -745,6 +942,11 @@ DATA FILTERS 41.144270897 -85.163655281 41.141953468 -85.162882805 + An arc file may optionally contain gaps in the arc. You can + specify such a gap by inserting a line containing "#break" + either on a line by itself or after the coordinates of the + starting point of the new arc segment. + In addition to the file containing the arc, you should also specify the maximum distance from the arc that will be accepted; that distance is declared on the command line with the @@ -915,69 +1117,3 @@ DATA FILTERS -x stack,pop,append \ -o magellan -F fwaind.wpt -COMMON USAGE - - Invocation was meant to be flexible. Unfortunately, that can - sometimes lead to unwieldy command lines. - - gpsbabel -? - - will always show you the supported file types. To use this - program, just tell it what you're reading, where to read it from, - what you're writing, and what to write it to. For example: - - gpsbabel -i geo -f /tmp/geocaching.loc -o gpx -F /tmp/geocaching.gpx - - tells it to read the first file in geocaching.com format and create - a new file in GPX format. - - This command will read from a Magellan unit attached to the first - serial port on a Linux system (device names will vary on other OSes) - and write them as a geocaching loc file. The second command does - the same for windows. - - gpsbabel -i magellan -f /dev/ttyS0 -o geo -F mag.loc - gpsbabel -i magellan -f com1 -o geo -F mag.loc - - - Optionally, you may specify "-s" in any command line. This causes - the program to ignore any "short" names that may be present in the - source data format and synthesize one from the long name. This - is particularly useful if you're writing to a target format that - isn't the lowest common denominator but the source data was written - for the lowest common denominator. I use this for writing data - from geocaching.com to my Magellan so my waypoints have "real" names - instead of the 'GC1234' ones that are optimized for NMEA-only - receivers. A geocacher with a Magellan receiver may thus find - commands like this useful. - - gpsbabel -s -i geo -f geocaching.loc -o magellan -F /dev/ttyS0 - gpsbabel -s -i geo -f geocaching.loc -o magellan -F com1 - -ADVANCED USAGE - - Argument are processed in the order they appear on the command line. - Input is cumulative. The input file type remains unchanged until a - new -i argument is seen. Files are read in the order they appear. - So you could merge three input files into one output file with: - - gpsbabel -i geo -f 1.loc -f 2.loc -f 3.loc -o geo -F big.loc - - You can merge files of different types: - - gpsbabel -i geo -f 1.loc -i gpx -f 2.gpx -i pcx 3.pcx -o gpsutil -F big.gps - - You can write the same data in different output formats: - - gpsbabel -i geo -f 1.loc -o gpx -F 1.gpx -o pcx 1.wpt - -ROUTE AND TRACK MODES - - The presence of "-t" on the command line tells us to work with - tracks. The presence of "-r" tells us to work with routes. - Tracks and routes are advanced features and don't try to - handle every possible hazard that can be encountered during a - conversion. If you're merging or converting files of similar - limitations, things work very well. The presence of "-s" on - the command line tends to creat havoc because tracks and routes. - diff --git a/an1.c b/an1.c new file mode 100644 index 000000000..63035f4c7 --- /dev/null +++ b/an1.c @@ -0,0 +1,835 @@ +/* + Read DeLorme drawing files (.an1) + + Copyright (C) 2005 Ron Parker and Robert Lipe. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + + */ + +#include +#include +#include + +#define MYNAME "an1" +#include "defs.h" + +FILE *infile; +FILE *outfile; + +static char *output_type = NULL; +long output_type_num = 0; + +static long serial=10000; +static long rtserial=1; + +static +arglist_t an1_args[] = { + {"type", &output_type, "Type of .an1 file (0=drawing)", + "0", ARGTYPE_HIDDEN | ARGTYPE_INT }, + {0, 0, 0, 0 } +}; + +typedef struct guid { + unsigned long l; + unsigned short s[3]; + unsigned char c[6]; +} GUID; + +#include "an1sym.h" + +static unsigned short +ReadShort(FILE * f) +{ + gbuint16 result = 0; + + fread(&result, sizeof (result), 1, f); + return le_read16(&result); +} + +static void +WriteShort(FILE * f, unsigned short s) +{ + gbuint16 tmp = 0; + le_write16( &tmp, s ); + fwrite( &tmp, sizeof(tmp), 1, f ); +} + +static unsigned long +ReadLong(FILE * f) +{ + gbuint32 result = 0; + + fread(&result, sizeof (result), 1, f); + return le_read32(&result); +} + +static void +WriteLong(FILE * f, unsigned long l) +{ + gbuint32 tmp = 0; + le_write32( &tmp, l ); + + fwrite( &tmp, sizeof(tmp), 1, f ); +} + +static double +ReadDouble( FILE * f ) +{ + double tmp = 0; + double result = 0; + fread(&tmp, sizeof(tmp),1,f); + le_read64(&result, &tmp ); + return result; +} + +static void +WriteDouble(FILE * f, double d) +{ + double tmp = 0; + le_read64( &tmp, (void *)&d ); + fwrite( &tmp, sizeof(tmp), 1, f ); +} + +static char * +ReadString( FILE * f, short len ) +{ + char *result = NULL; + result = (char *)xcalloc( 1, len + 1 ); + if ( len ) { + fread( result, 1, len, f ); + } + return result; +} + +static unsigned char +ReadChar( FILE *f ) +{ + unsigned char result = 0; + fread( &result, 1, 1, f ); + return result; +} + +static void +WriteChar( FILE *f, unsigned char c ) +{ + fwrite( &c, 1, 1, f ); +} + +static void +WriteString( FILE *f, char *s ) +{ + fwrite( s, 1, strlen(s), f ); +} + +static void +ReadGuid( FILE *f, GUID *guid ) +{ + int i = 0; + guid->l = ReadLong( f ); + for ( i = 0; i < 3; i++ ) { + guid->s[i] = ReadShort( f ); + } + for ( i = 0; i < 6; i++ ) { + guid->c[i] = ReadChar( f ); + } +} + +static void +WriteGuid( FILE *f, GUID *guid ) +{ + int i = 0; + WriteLong( f, guid->l ); + for ( i = 0; i < 3; i++ ) { + WriteShort( f, guid->s[i] ); + } + for ( i = 0; i < 6; i++ ) { + WriteChar( f, guid->c[i] ); + } +} + +static void +Skip(FILE * f, + unsigned long distance) +{ + fseek(f, distance, SEEK_CUR); +} + +static double +DecodeOrd( long ord ) +{ + return (double)(0x80000000-ord)/(0x800000); +} + +static long +EncodeOrd( double ord ) +{ + unsigned long tmp = ord * 0x800000; + return 0x80000000UL-tmp; +} + +static int +IsGuidEqual( GUID *a, GUID *b ) +{ + return !memcmp( a, b, sizeof( GUID )); +} + +typedef struct { + short hotspotxhi; + long hotspoty; + long unk1; + GUID guid; + char *name; +} an1_symbol_record; + +typedef struct { + an1_base base; + short magic; + long unk1; + long lon; + long lat; + short type; + long height; + long width; + short unk2; + short unk3; + short serial; + short unk4; + unsigned char create_zoom; + unsigned char visible_zoom; + short unk5; + double radius; + char *name; + char *fontname; + GUID guid; + long fontcolor; + long fontstyle; + long fontsize; + long outlineweight; + long outlinecolor; + long outlineflags; + long fillcolor; + long unk6; + long fillflags; +} an1_waypoint_record; + +typedef struct { + an1_base base; + short magic; + long unk0; + long lon; + long lat; + short unk1; +} an1_vertex_record; + +typedef struct { + an1_base base; + short magic; + short unk1; + short serial; + long unk2; + short unk3; + short type; + long unk4; + char *name; + long lineweight; + long linestyle; + long linecolor; + long unk5; + long polyfillcolor; + long unk6; + long unk7; + short unk8; + long pointcount; +} an1_line_record; + +static an1_waypoint_record *Alloc_AN1_Waypoint( ); + +void Destroy_AN1_Waypoint( void *vwpt ) { + an1_waypoint_record *wpt = (an1_waypoint_record *)vwpt; + xfree( wpt->name ); + xfree( wpt->fontname ); +} + +void Copy_AN1_Waypoint( void **vdwpt, void *vwpt ) { + an1_waypoint_record *wpt = (an1_waypoint_record *)vwpt; + an1_waypoint_record *dwpt = Alloc_AN1_Waypoint(); + memcpy( dwpt, wpt, sizeof( an1_waypoint_record )); + dwpt->name = xstrdup( wpt->name ); + dwpt->fontname = xstrdup( wpt->fontname ); + *vdwpt = (void *)dwpt; +} + +static an1_waypoint_record *Alloc_AN1_Waypoint( ) { + an1_waypoint_record *result = NULL; + result = (an1_waypoint_record *)xcalloc( sizeof(*result), 1 ); + result->base.copy = Copy_AN1_Waypoint; + result->base.destroy = Destroy_AN1_Waypoint; +} + +static an1_vertex_record *Alloc_AN1_Vertex(); + +void Destroy_AN1_Vertex( void *vvertex ) { + /* do nothing */ +} + +void Copy_AN1_Vertex( void **vdvert, void *vvert ) { + an1_vertex_record *vert = (an1_vertex_record *)vvert; + an1_vertex_record *dvert = Alloc_AN1_Vertex(); + memcpy( dvert, vert, sizeof( an1_vertex_record )); + *vdvert = (void *)dvert; +} + +static an1_vertex_record *Alloc_AN1_Vertex() { + an1_vertex_record *result = NULL; + result = (an1_vertex_record *)xcalloc( sizeof( *result), 1 ); + result->base.copy = Copy_AN1_Vertex; + result->base.destroy = Destroy_AN1_Vertex; +} + + +static an1_line_record *Alloc_AN1_Line(); + +void Destroy_AN1_Line( void *vline ) { + an1_line_record *line = (an1_line_record *)vline; + xfree( line->name ); +} + +void Copy_AN1_Line( void **vdline, void *vline ) { + an1_line_record *line = (an1_line_record *)vline; + an1_line_record *dline = Alloc_AN1_Line(); + memcpy( dline, line, sizeof( an1_line_record )); + dline->name = xstrdup( line->name ); + *vdline = (void *)dline; +} + +static an1_line_record *Alloc_AN1_Line( ) { + an1_line_record *result = NULL; + result = (an1_line_record *)xcalloc( sizeof(*result), 1 ); + result->base.copy = Copy_AN1_Line; + result->base.destroy = Destroy_AN1_Line; +} + + +static void Destroy_AN1_Symbol( an1_symbol_record *symbol ) { + xfree( symbol->name ); +} + +static void Read_AN1_Waypoint( FILE *f, an1_waypoint_record *wpt ) { + short len; + + wpt->magic = ReadShort( f ); + wpt->unk1 = ReadLong( f ); + wpt->lon = ReadLong( f ); + wpt->lat = ReadLong( f ); + wpt->type = ReadShort( f ); + wpt->height = ReadLong( f ); + wpt->width = ReadLong( f ); + wpt->unk2 = ReadShort( f ); + wpt->unk3 = ReadShort( f ); + wpt->serial = ReadShort( f ); + wpt->unk4 = ReadShort( f ); + wpt->create_zoom = ReadChar( f ); + wpt->visible_zoom = ReadChar( f ); + wpt->unk5 = ReadShort( f ); + wpt->radius = ReadDouble( f ); + len = ReadShort( f ); + wpt->name = ReadString( f, len ); + len = ReadShort( f ); + wpt->fontname = ReadString( f, len ); + ReadGuid( f, &wpt->guid ); + wpt->fontcolor = ReadLong( f ); + wpt->fontstyle = ReadLong( f ); + wpt->fontsize = ReadLong( f ); + wpt->outlineweight = ReadLong( f ); + wpt->outlinecolor = ReadLong( f ); + wpt->outlineflags = ReadLong( f ); + wpt->fillcolor = ReadLong( f ); + wpt->unk6 = ReadLong( f ); + wpt->fillflags = ReadLong( f ); +} + +static void Write_AN1_Waypoint( FILE *f, an1_waypoint_record *wpt ) { + short len; + + WriteShort( f, wpt->magic ); + WriteLong( f, wpt->unk1 ); + WriteLong( f, wpt->lon ); + WriteLong( f, wpt->lat ); + WriteShort( f, wpt->type ); + WriteLong( f, wpt->height ); + WriteLong( f, wpt->width ); + WriteShort( f, wpt->unk2 ); + WriteShort( f, wpt->unk3 ); + WriteShort( f, wpt->serial ); + WriteShort( f, wpt->unk4 ); + WriteChar( f, wpt->create_zoom ); + WriteChar( f, wpt->visible_zoom ); + WriteShort( f, wpt->unk5 ); + WriteDouble( f, wpt->radius ); + len = strlen( wpt->name ); + WriteShort( f, len ); + WriteString( f, wpt->name ); + len = strlen( wpt->fontname ); + WriteShort( f, len ); + WriteString( f, wpt->fontname ); + WriteGuid( f, &wpt->guid ); + WriteLong( f, wpt->fontcolor ); + WriteLong( f, wpt->fontstyle ); + WriteLong( f, wpt->fontsize ); + WriteLong( f, wpt->outlineweight ); + WriteLong( f, wpt->outlinecolor ); + WriteLong( f, wpt->outlineflags ); + WriteLong( f, wpt->fillcolor ); + WriteLong( f, wpt->unk6 ); + WriteLong( f, wpt->fillflags ); +} + +static void Read_AN1_Vertex( FILE *f, an1_vertex_record *vertex ) { + + vertex->magic = ReadShort( f ); + vertex->unk0 = ReadLong( f ); + vertex->lon = ReadLong( f ); + vertex->lat = ReadLong( f ); + vertex->unk1 = ReadShort( f ); +} + +static void Write_AN1_Vertex( FILE *f, an1_vertex_record *vertex ) { + WriteShort( f, vertex->magic ); + WriteLong( f, vertex->unk0 ); + WriteLong( f, vertex->lon ); + WriteLong( f, vertex->lat ); + WriteShort( f, vertex->unk1 ); +} + +static void Read_AN1_Line( FILE *f, an1_line_record *line ) { + + short len; + + line->magic = ReadShort( f ); + line->unk1 = ReadShort( f ); + line->serial = ReadShort( f ); + line->unk2 = ReadLong( f ); + line->unk3 = ReadShort( f ); + line->type = ReadShort( f ); + line->unk4 = ReadLong( f ); + len = ReadShort( f ); + line->name = ReadString( f, len ); + line->lineweight = ReadShort( f ); + line->linestyle = ReadLong( f ); + line->linecolor = ReadLong( f ); + line->unk5 = ReadLong( f ); + line->polyfillcolor = ReadLong( f ); + line->unk6 = ReadLong( f ); + line->unk7 = ReadLong( f ); + line->unk8 = ReadShort( f ); + line->pointcount = ReadLong( f ); +} + +static void Write_AN1_Line( FILE *f, an1_line_record *line ) { + short len; + + WriteShort( f, line->magic ); + WriteShort( f, line->unk1 ); + WriteShort( f, line->serial ); + WriteLong( f, line->unk2 ); + WriteShort( f, line->unk3 ); + WriteShort( f, line->type ); + WriteLong( f, line->unk4 ); + len = strlen( line->name ); + WriteShort( f, len ); + WriteString( f, line->name ); + WriteShort( f, line->lineweight ); + WriteLong( f, line->linestyle ); + WriteLong( f, line->linecolor ); + WriteLong( f, line->unk5 ); + WriteLong( f, line->polyfillcolor ); + WriteLong( f, line->unk6 ); + WriteLong( f, line->unk7 ); + WriteShort( f, line->unk8 ); + WriteLong( f, line->pointcount ); +} + +static void Skip_AN1_IL( FILE *f ) { + Skip( f, 26 ); +} + +static void Skip_AN1_BM( FILE *f ) { + unsigned long bmsize; + unsigned long palettesize; + unsigned long bmisize; + unsigned long bitoffset; + + Skip( f, 8 ); /* BITMAPFILEHEADER fields 1-3 */ + bitoffset = ReadLong( f ); + + bmisize = ReadLong( f ); + Skip( f, 16 ); /* BITMAPINFOHEADER fields 2-6 */ + bmsize = ReadLong( f ); + Skip( f, 16 ); /* BITMAPINFOHEADER fields 8-11 */ + + palettesize = bitoffset - bmisize - 14; + Skip( f, bmsize + palettesize ); +} + +static void Read_AN1_Symbol( FILE *f, an1_symbol_record *symbol ) { + short len; + + /* This is just the high word of a long; we ate the low + * word in the caller. Fortunately, we don't care. */ + symbol->hotspotxhi = ReadShort( f ); + symbol->hotspoty = ReadLong( f ); + symbol->unk1 = ReadLong( f ); + ReadGuid( f, &symbol->guid ); + len = ReadChar( f ); + symbol->name = ReadString( f, len ); +} + +static void Read_AN1_Header( FILE *f ) { + unsigned short magic; + unsigned short type; + + magic = ReadShort( f ); + type = ReadShort( f ); +} + +static void Write_AN1_Header( FILE *f ) { + WriteShort( f, 11557 ); + WriteShort( f, atoi( output_type ) ); +} + +static void Read_AN1_Bitmaps( FILE *f ) { + long count; + unsigned short magic; + an1_symbol_record symbol; + + count = ReadLong( f ); + + while ( count ) { + magic = ReadShort( f ); + switch (magic) { + case 0x4d42: + Skip_AN1_BM( f ); + break; + case 0x4c49: + Skip_AN1_IL( f ); + break; + default: + Read_AN1_Symbol( f, &symbol ); + Destroy_AN1_Symbol( &symbol ); + count--; + break; + } + } + + /* Read the symbol table */ +} + +static void Write_AN1_Bitmaps( FILE *f ) { + /* On write, we don't output any bitmaps, so writing them + * is just a matter of writing a count of zero */ + WriteLong( f, 0 ); +} + +static void Read_AN1_Waypoints( FILE *f ) { + unsigned long count = 0; + unsigned long i = 0; + an1_waypoint_record *rec = NULL; + waypoint *wpt_tmp; + char *icon = NULL; + ReadShort( f ); + count = ReadLong( f ); + for (i = 0; i < count; i++ ) { + rec = Alloc_AN1_Waypoint(); + Read_AN1_Waypoint( f, rec ); + wpt_tmp = waypt_new(); + + wpt_tmp->longitude = -DecodeOrd( rec->lon ); + wpt_tmp->latitude = DecodeOrd( rec->lat ); + wpt_tmp->description = xstrdup( rec->name ); + + if (FindIconByGuid(&rec->guid, &icon)) { + wpt_tmp->icon_descr = icon; + } + + wpt_tmp->an1_extras = (an1_base *)(void *)rec; + rec = NULL; + waypt_add( wpt_tmp ); + } +} + +static void +Write_One_AN1_Waypoint( const waypoint *wpt ) +{ + an1_waypoint_record *rec; + int local; + + if ( wpt->an1_extras ) { + rec = (an1_waypoint_record *)(void *)(wpt->an1_extras); + xfree( rec->name ); + local = 0; + } + else { + rec = Alloc_AN1_Waypoint(); + local = 1; + rec->magic = 1; + rec->type = 1; + rec->unk2 = 3; + rec->unk3 = 18561; + rec->fontname = xstrdup( "Arial" ); + FindIconByName( "Red Flag", &rec->guid ); + rec->fontsize = 10; + } + rec->name = xstrdup( wpt->description ); + rec->lat = EncodeOrd( wpt->latitude ); + rec->lon = EncodeOrd( -wpt->longitude ); + rec->serial = serial++; + + if ( wpt->icon_descr ) { + FindIconByName( (char *)(void *)wpt->icon_descr, &rec->guid ); + } + + Write_AN1_Waypoint( outfile, rec ); + if ( local ) { + Destroy_AN1_Waypoint( rec ); + xfree( rec ); + } +} + +static void Write_AN1_Waypoints( FILE *f ) { + WriteShort( f, 2 ); + WriteLong( f, waypt_count() ); + waypt_disp_all( Write_One_AN1_Waypoint ); +} + +static void Read_AN1_Lines( FILE *f ) { + unsigned long count = 0; + unsigned long i = 0; + unsigned long j = 0; + an1_line_record *rec = NULL; + an1_vertex_record *vert = NULL; + route_head *rte_head; + waypoint *wpt_tmp; + + ReadShort( f ); + count = ReadLong( f ); + for (i = 0; i < count; i++ ) { + rec = Alloc_AN1_Line(); + Read_AN1_Line( f, rec ); + /* create route rec */ + rte_head = route_head_alloc(); + rte_head->an1_extras = (an1_base *)(void *)rec; + route_add_head(rte_head); + for (j = 0; j < rec->pointcount; j++ ) { + vert = Alloc_AN1_Vertex(); + Read_AN1_Vertex( f, vert ); + + /* create route point */ + wpt_tmp = waypt_new(); + wpt_tmp->latitude = DecodeOrd( vert->lat ); + wpt_tmp->longitude = -DecodeOrd( vert->lon ); + wpt_tmp->shortname = (char *) xmalloc(7); + sprintf( wpt_tmp->shortname, "\\%5.5x", rtserial++ ); + wpt_tmp->an1_extras = (an1_base *)(void *)vert; + route_add_wpt(rte_head, wpt_tmp); + } + } +} + +static void +Write_One_AN1_Line( const route_head *rte ) +{ + an1_line_record *rec; + int local; + + if ( rte->an1_extras ) { + rec = (an1_line_record *)(void *)(rte->an1_extras); + local = 0; + switch (output_type_num) { + case 1: + if ( rec->type != 14 ) { + rec = Alloc_AN1_Line(); + memcpy( rec, rte->an1_extras, sizeof(an1_line_record)); + local = 1; + rec->magic = 4112; + rec->unk1 = 4359; + rec->unk2 = 655360; + rec->type = 14; + rec->unk8 = 2; + } // end if + break; + case 2: + if ( rec->type != 15 ) { + rec = Alloc_AN1_Line(); + memcpy( rec, rte->an1_extras, sizeof(an1_line_record)); + local = 1; + rec->type = 15; + } // end if + break; + case 4: + if ( rec->type != 16 ) { + rec = Alloc_AN1_Line(); + memcpy( rec, rte->an1_extras, sizeof(an1_line_record)); + local = 1; + rec->type = 16; + } // end if + break; + } + } + else { + rec = Alloc_AN1_Line(); + local = 1; + switch (output_type_num) { + /* drawing road trail waypoint track */ + case 1: /* road */ + rec->magic = 4112; + rec->unk1 = 4359; + rec->unk2 = 655360; + rec->type = 14; + rec->unk8 = 2; + break; + + case 2: /* trail */ + rec->magic = 7248; + rec->unk1 = 4359; + rec->unk2 = 917504; + rec->type = 15; + rec->unk8 = 2; + break; + + case 4: /* track */ + rec->magic = 21; + rec->unk1 = 18560; + rec->unk2 = 917504; + rec->type = 16; + rec->unk4 = 2; + rec->unk8 = 2; + break; + + case 0: /* drawing */ + case 3: /* waypoint - shouldn't have lines */ + default: + rec->magic = 21; + rec->unk1 = 18560; + rec->unk2 = 1048576; + rec->type = 2; + rec->unk4 = 2; + rec->lineweight = 6; + rec->linecolor = 255; /* red */ + rec->unk5 = 3; + rec->unk8 = 2; + break; + } + rec->name = xstrdup( "" ); + + } + rec->serial = serial++; + rec->pointcount = rte->rte_waypt_ct; + Write_AN1_Line( outfile, rec ); + if ( local ) { + Destroy_AN1_Line( rec ); + xfree( rec ); + } +} + +static void +Write_One_AN1_Vertex( const waypoint *wpt ) +{ + an1_vertex_record *rec; + int local; + + if ( wpt->an1_extras ) { + rec = (an1_vertex_record *)(void *)(wpt->an1_extras); + local = 0; + } + else { + rec = Alloc_AN1_Vertex(); + local = 1; + rec->magic = 1; + } + rec->lat = EncodeOrd( wpt->latitude ); + rec->lon = EncodeOrd( -wpt->longitude ); + + Write_AN1_Vertex( outfile, rec ); + if ( local ) { + Destroy_AN1_Vertex( rec ); + xfree( rec ); + } +} + +static void Write_AN1_Lines( FILE *f ) { + WriteShort( f, 2 ); + WriteLong( f, route_count()+track_count() ); + + route_disp_all( Write_One_AN1_Line, NULL, Write_One_AN1_Vertex ); + track_disp_all( Write_One_AN1_Line, NULL, Write_One_AN1_Vertex ); +} + +static void +rd_init(const char *fname) +{ + infile = xfopen(fname, "rb", MYNAME); + output_type_num = atoi( output_type ); +} + +static void +rd_deinit(void) +{ + fclose(infile); +} + +static void +my_read(void) +{ + Read_AN1_Header( infile ); + Read_AN1_Bitmaps( infile ); + Read_AN1_Waypoints( infile ); + Read_AN1_Lines( infile ); +} + +static void +wr_init(const char *fname) +{ + outfile = xfopen( fname, "wb", MYNAME ); + output_type_num = atoi( output_type ); +} + +static void +wr_deinit( void ) +{ + fclose(outfile); +} + +static void +my_write( void ) +{ + Write_AN1_Header( outfile ); + Write_AN1_Bitmaps( outfile ); + Write_AN1_Waypoints( outfile ); + Write_AN1_Lines( outfile ); +} + +ff_vecs_t an1_vecs = { + ff_type_file, + FF_CAP_RW_ALL, + rd_init, + wr_init, + rd_deinit, + wr_deinit, + my_read, + my_write, + NULL, + an1_args +}; diff --git a/an1sym.h b/an1sym.h new file mode 100644 index 000000000..8c5f0b41d --- /dev/null +++ b/an1sym.h @@ -0,0 +1,519 @@ +/* + + + + + + + + + + THIS FILE IS AUTOMATICALLY GENERATED + + + Please change make-an1sym.pl and + regenerate it rather than changing + this file directly. + + + + + + + + + + + + + + + + + + + + + + + +*/ + +/* + Read DeLorme drawing files (.an1) - supplemental (included by an1.c) + + Copyright (C) 2005 Ron Parker and Robert Lipe. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + + */ + +struct defguid { + GUID guid; + char *name; +} default_guids[] = { + {{0xb610bc70,{0x377e, 0x11d6, 0xaeb3}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Hiker"}, + {{0xb610bc71,{0x377e, 0x11d6, 0xaeb3}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Canoe"}, + {{0xb610bc72,{0x377e, 0x11d6, 0xaeb3}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Kayak"}, + {{0xb610bc73,{0x377e, 0x11d6, 0xaeb3}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Bike"}, + {{0xb610bc74,{0x377e, 0x11d6, 0xaeb3}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Four wheeler"}, + {{0xb610bc75,{0x377e, 0x11d6, 0xaeb3}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Jeep"}, + {{0xb610bc76,{0x377e, 0x11d6, 0xaeb3}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Snowmobile"}, + {{0xb610bc78,{0x377e, 0x11d6, 0xaeb3}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Rec Vehicle"}, + {{0xb610bc79,{0x377e, 0x11d6, 0xaeb3}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Fire"}, + {{0xb610bc7a,{0x377e, 0x11d6, 0xaeb3}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Fishing"}, + {{0xb610bc7b,{0x377e, 0x11d6, 0xaeb3}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Tree"}, + {{0xb610bc7c,{0x377e, 0x11d6, 0xaeb3}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Pine Tree"}, + {{0xb610bc7d,{0x377e, 0x11d6, 0xaeb3}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Birch"}, + {{0xb610bc7e,{0x377e, 0x11d6, 0xaeb3}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Deer"}, + {{0xb610bc7f,{0x377e, 0x11d6, 0xaeb3}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Moose"}, + {{0x99d8c163,{0x7622, 0x11d5, 0xe8ae}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Mud"}, + {{0x012dfac2,{0xade8, 0x11d5, 0x0fb3}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Tractor"}, + {{0x012dfac3,{0xade8, 0x11d5, 0x0fb3}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Combine Harvester"}, + {{0x012dfac7,{0xade8, 0x11d5, 0x0fb3}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Front-End Loader"}, + {{0xfd163780,{0xb10a, 0x11d5, 0x11b3}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Power Shovel"}, + {{0xfd163781,{0xb10a, 0x11d5, 0x11b3}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Road Grader"}, + {{0xfd163784,{0xb10a, 0x11d5, 0x11b3}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Road Roller"}, + {{0xfd163787,{0xb10a, 0x11d5, 0x11b3}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Dump Truck"}, + {{0x5673d712,{0xb28d, 0x11d5, 0x13b3}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Skid-Steer Loader"}, + {{0xb86045ac,{0x390f, 0x420f, 0x91a7}, {0x76, 0x2f, 0x48, 0xea, 0xe2, 0xd7}}, + "Highway Sign"}, + {{0x1e129e95,{0x13b6, 0x48d8, 0x3fa3}, {0x9c, 0xc8, 0x20, 0x8e, 0x1d, 0x9d}}, + "Orange Cone"}, + {{0xadee7d54,{0xf7c9, 0x4ab6, 0xfb93}, {0x99, 0xc3, 0xbc, 0x9d, 0x15, 0x47}}, + "Barricade"}, + {{0xa170000f,{0x8bd8, 0x4574, 0x58ac}, {0x55, 0x41, 0x67, 0xef, 0x64, 0x62}}, + "Flagger"}, + {{0xa425f90e,{0x6ab6, 0x4ca9, 0x8997}, {0xbf, 0xca, 0xe0, 0xc2, 0x2b, 0x53}}, + "Construction Sign"}, + {{0x0805b240,{0x6b26, 0x4300, 0xebb1}, {0xea, 0x9b, 0xcf, 0x68, 0xc6, 0x18}}, + "Construction Flasher"}, + {{0x56721a6c,{0x8e77, 0x4b62, 0x09aa}, {0xce, 0xdc, 0x69, 0x4a, 0x16, 0x05}}, + "Transit"}, + {{0x623e1ee9,{0xaf27, 0x11d3, 0x29bc}, {0x00, 0x50, 0x04, 0x02, 0xf5, 0x32}}, + "Arrow Left"}, + {{0x623e1eea,{0xaf27, 0x11d3, 0x29bc}, {0x00, 0x50, 0x04, 0x02, 0xf5, 0x32}}, + "Arrow Right"}, + {{0x623e1eeb,{0xaf27, 0x11d3, 0x29bc}, {0x00, 0x50, 0x04, 0x02, 0xf5, 0x32}}, + "Arrow Up"}, + {{0x623e1eec,{0xaf27, 0x11d3, 0x29bc}, {0x00, 0x50, 0x04, 0x02, 0xf5, 0x32}}, + "Arrow Down"}, + {{0x623e1eed,{0xaf27, 0x11d3, 0x29bc}, {0x00, 0x50, 0x04, 0x02, 0xf5, 0x32}}, + "Arrow Up Left"}, + {{0x623e1eee,{0xaf27, 0x11d3, 0x29bc}, {0x00, 0x50, 0x04, 0x02, 0xf5, 0x32}}, + "Arrow Up Right"}, + {{0x623e1eef,{0xaf27, 0x11d3, 0x29bc}, {0x00, 0x50, 0x04, 0x02, 0xf5, 0x32}}, + "Arrow Down Left"}, + {{0x623e1ef0,{0xaf27, 0x11d3, 0x29bc}, {0x00, 0x50, 0x04, 0x02, 0xf5, 0x32}}, + "Arrow Down Right"}, + {{0x83f91421,{0x3772, 0x11d6, 0xaeb3}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Small Arrow Left"}, + {{0x83f91422,{0x3772, 0x11d6, 0xaeb3}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Small Arrow Right"}, + {{0x83f91423,{0x3772, 0x11d6, 0xaeb3}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Small Arrow Up"}, + {{0x83f91424,{0x3772, 0x11d6, 0xaeb3}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Small Arrow Down"}, + {{0x83f91425,{0x3772, 0x11d6, 0xaeb3}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Small Arrow Up Left"}, + {{0x83f91426,{0x3772, 0x11d6, 0xaeb3}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Small Arrow Up Right"}, + {{0x83f91427,{0x3772, 0x11d6, 0xaeb3}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Small Arrow Down Left"}, + {{0x83f91428,{0x3772, 0x11d6, 0xaeb3}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Small Arrow Down Right"}, + {{0x83f91429,{0x3772, 0x11d6, 0xaeb3}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Large Arrow Left"}, + {{0x83f9142a,{0x3772, 0x11d6, 0xaeb3}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Large Arrow Right"}, + {{0x83f9142b,{0x3772, 0x11d6, 0xaeb3}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Large Arrow Up"}, + {{0x83f9142c,{0x3772, 0x11d6, 0xaeb3}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Large Arrow Down"}, + {{0x83f9142d,{0x3772, 0x11d6, 0xaeb3}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Large Arrow Down Right"}, + {{0x83f9142e,{0x3772, 0x11d6, 0xaeb3}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Large Arrow Down Left"}, + {{0x83f9142f,{0x3772, 0x11d6, 0xaeb3}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Large Arrow Up Left"}, + {{0x83f91430,{0x3772, 0x11d6, 0xaeb3}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Large Arrow Up Right"}, + {{0x8ff0aad1,{0xc53d, 0x4998, 0x7ebd}, {0x06, 0x60, 0x25, 0x6c, 0x4f, 0x6d}}, + "Accommodation"}, + {{0xaf7bf199,{0x6a8b, 0x49fe, 0xae92}, {0xa3, 0x09, 0x7b, 0xb8, 0x81, 0x6a}}, + "Australia"}, + {{0x6bbcc9d1,{0x6a19, 0x4c7b, 0xc6a2}, {0x3e, 0x17, 0x02, 0xd6, 0xee, 0x3a}}, + "Blue Dome Cross"}, + {{0xfff920fe,{0xd780, 0x49d4, 0x1bad}, {0x55, 0x2e, 0xc7, 0xdf, 0xa2, 0xaa}}, + "Green Dome Cross"}, + {{0x57e75924,{0xd6fa, 0x4666, 0x84bf}, {0x5b, 0x76, 0xa1, 0xd0, 0x14, 0x5f}}, + "Business"}, + {{0xb09ef4a7,{0x95e4, 0x4e5e, 0x5e84}, {0xbe, 0x2b, 0x86, 0xdd, 0x50, 0x65}}, + "Airplane"}, + {{0xf2833c22,{0x3592, 0x4a8a, 0x5693}, {0xee, 0x6c, 0x83, 0xb6, 0x3c, 0x19}}, + "Amusement Recreation"}, + {{0x6f0317d6,{0x7fa3, 0x4dcc, 0x6187}, {0x7e, 0xca, 0xcb, 0x65, 0x49, 0x12}}, + "Green Square"}, + {{0x18a6d3c0,{0x45cb, 0x4d19, 0xf5b9}, {0xc7, 0x9c, 0xbf, 0x8f, 0x6d, 0x46}}, + "Red Triangle"}, + {{0x86e68ea7,{0xb9ab, 0x4bc8, 0xa1bf}, {0xc1, 0x22, 0x13, 0x97, 0x95, 0xe8}}, + "Red Triangle and Green Square"}, + {{0x6afd74bf,{0x0ea5, 0x4680, 0xcd88}, {0x15, 0x87, 0x2f, 0x6c, 0xd2, 0xd8}}, + "City 4"}, + {{0x49dfeb74,{0xbb09, 0x4df1, 0x5687}, {0xd8, 0xa0, 0xff, 0x36, 0x89, 0x3d}}, + "White Square"}, + {{0x3eed62c6,{0xdab9, 0x42b0, 0xe4a3}, {0xd2, 0xf1, 0x7d, 0x54, 0xbf, 0x77}}, + "White Triangle"}, + {{0x6b521940,{0x4492, 0x4c48, 0x58a0}, {0xfc, 0xd1, 0x1f, 0x5e, 0x0c, 0xea}}, + "Red Black Diamond Flag"}, + {{0xbb8ebaa3,{0xac59, 0x4411, 0x9c94}, {0x30, 0xd4, 0xe1, 0x21, 0x25, 0x46}}, + "Yellow Diamond Flag"}, + {{0x8e118862,{0xf6aa, 0x4b34, 0x2b82}, {0x8f, 0x3b, 0x5a, 0x2b, 0x59, 0xeb}}, + "Small Pink Square"}, + {{0xd0ef64c2,{0xe319, 0x4876, 0x1b85}, {0x0e, 0x90, 0x50, 0x89, 0xb7, 0xc5}}, + "Store"}, + {{0xa22b08fb,{0x6193, 0x4f5c, 0xdaa4}, {0xfa, 0xdf, 0xa7, 0x6e, 0x23, 0xe1}}, + "Camping"}, + {{0x27f57c69,{0x575b, 0x4b56, 0x288c}, {0xe8, 0xe1, 0xc7, 0x05, 0x1f, 0x1f}}, + "Green Diamond Flag"}, + {{0xe07abb38,{0x219f, 0x4b52, 0x868b}, {0x45, 0x0f, 0xbc, 0xc1, 0x4f, 0x6a}}, + "Red Diamond Flag"}, + {{0x3a124ac9,{0x3973, 0x4e27, 0x4b82}, {0xa6, 0x3a, 0x94, 0x5c, 0xf8, 0xb3}}, + "Red Green Diamond Flag"}, + {{0x64ed669b,{0x0db8, 0x4ec9, 0xd181}, {0x98, 0x50, 0xb3, 0x8b, 0x2f, 0x2e}}, + "White Globe"}, + {{0x3cb10adc,{0xb090, 0x4960, 0x9f8a}, {0xec, 0xaf, 0x6c, 0xd7, 0xaa, 0x8b}}, + "Yellow Globe"}, + {{0x2779347d,{0x17d4, 0x4021, 0xa6a8}, {0x51, 0x9a, 0xb6, 0xf8, 0x21, 0xff}}, + ""}, + {{0x3ad63f7b,{0x4339, 0x427d, 0x5797}, {0xce, 0xa9, 0x96, 0x33, 0x8b, 0x3c}}, + "Black Cross"}, + {{0x3e89481e,{0x35ff, 0x48b6, 0xc7ae}, {0xb0, 0x75, 0xf6, 0x43, 0xc4, 0xc7}}, + "Church"}, + {{0x68622c10,{0x79b6, 0x466d, 0xa8a3}, {0x27, 0xc6, 0x25, 0x34, 0xfa, 0xa9}}, + "Small Dark Green Square"}, + {{0x42c6a873,{0x2d0c, 0x46e7, 0x9989}, {0xdd, 0x86, 0x01, 0x6e, 0xa4, 0xc9}}, + "Small Black Square"}, + {{0x50e3b06e,{0xbe81, 0x4b2c, 0x1f92}, {0x80, 0xa5, 0x72, 0x9b, 0x33, 0x05}}, + "Danger"}, + {{0x369d0b22,{0xed07, 0x421f, 0x8780}, {0x33, 0x0e, 0xbd, 0x27, 0x4f, 0x3c}}, + "Construction Business"}, + {{0x10603b6c,{0xb02e, 0x49ee, 0x60b9}, {0xed, 0x7e, 0x31, 0x16, 0x27, 0x89}}, + "Airport"}, + {{0x8328aab7,{0xfe04, 0x46dc, 0x7bbf}, {0x29, 0x34, 0x30, 0xd3, 0x4d, 0xeb}}, + "City 5"}, + {{0x96411287,{0xda33, 0x40e3, 0xaa9c}, {0x75, 0x83, 0x78, 0x2d, 0xa6, 0xf3}}, + "USA"}, + {{0xb2f98627,{0x1211, 0x40e8, 0xb287}, {0x6d, 0x66, 0xfd, 0x15, 0x1e, 0xd4}}, + "Diver Down"}, + {{0x3fce26d0,{0xfec6, 0x4f8b, 0x55a2}, {0x89, 0x3a, 0x8e, 0x59, 0x08, 0x0a}}, + "Light Yellow Square"}, + {{0xb4b68597,{0x1aed, 0x4918, 0xd492}, {0x1f, 0xd1, 0x5e, 0xf2, 0x55, 0xc1}}, + "Education Technology"}, + {{0x35d2e6a8,{0xda88, 0x4edb, 0x4b80}, {0x2b, 0x1b, 0xcf, 0xc0, 0xd4, 0x6d}}, + "Computer"}, + {{0x4ddc4e96,{0x8d19, 0x4079, 0x4488}, {0xc0, 0x8f, 0x0f, 0x8e, 0xb5, 0xd7}}, + "Amusement Recreation Red"}, + {{0x79f58929,{0x46c6, 0x4337, 0xc0b1}, {0xf0, 0x09, 0x55, 0xbb, 0x1f, 0xc3}}, + "Telephone Red"}, + {{0x0083b377,{0xfb80, 0x4a83, 0x3593}, {0x56, 0xe5, 0xfe, 0xc4, 0xcd, 0x43}}, + "Exit"}, + {{0x0c232891,{0xab4d, 0x440e, 0x7083}, {0x05, 0x63, 0x3a, 0xf5, 0x66, 0x11}}, + "Exit with Services"}, + {{0xaf63e7c2,{0x03fa, 0x418e, 0xc68b}, {0x02, 0xb8, 0xf5, 0x61, 0xb6, 0x61}}, + "Pizza"}, + {{0xd419c693,{0x39e6, 0x43db, 0xa1b8}, {0x7f, 0xcc, 0x2c, 0xb8, 0x51, 0x4a}}, + "Financial Services"}, + {{0x70740a81,{0xe4ca, 0x4ac2, 0xa498}, {0x21, 0xc8, 0x5b, 0xc0, 0xb7, 0xae}}, + "City 3"}, + {{0x9a582ff6,{0x34c4, 0x41c6, 0xf0a3}, {0x99, 0x69, 0x9d, 0xbe, 0x2e, 0x08}}, + "Food Store"}, + {{0x3cd31689,{0x2f8f, 0x4fb0, 0xcb88}, {0x34, 0x84, 0xfc, 0x8b, 0x03, 0xe4}}, + ""}, + {{0x952557a6,{0xe29e, 0x4512, 0x1184}, {0x1a, 0x3c, 0x9c, 0xd4, 0x83, 0x7d}}, + ""}, + {{0x03dc278c,{0xe8ff, 0x46ac, 0x3daa}, {0x9f, 0xe9, 0x1e, 0xcf, 0x10, 0x35}}, + "Driving Range"}, + {{0xacd28bab,{0x0ec0, 0x4393, 0xaf8b}, {0xbb, 0x5e, 0x74, 0xb3, 0x87, 0x12}}, + "Golf Municipal"}, + {{0x984e7139,{0xeab8, 0x49f6, 0x55a0}, {0x8d, 0x51, 0xe6, 0xdd, 0xcc, 0xf4}}, + "Golf Private"}, + {{0xec5828ab,{0x2a9d, 0x48f8, 0xd79b}, {0xc9, 0xc3, 0x30, 0x8e, 0xe4, 0xea}}, + "Golf Public"}, + {{0xb0120d99,{0x683a, 0x4ecc, 0x129a}, {0x29, 0x94, 0x1f, 0x04, 0xae, 0x10}}, + "Golf Resort"}, + {{0x2ce7685a,{0x6eaf, 0x4061, 0x29a5}, {0x87, 0x5e, 0xfa, 0x41, 0x75, 0x1a}}, + "Golf Semi Private"}, + {{0x10397049,{0x9fc9, 0x4380, 0x5680}, {0x81, 0xd9, 0xe7, 0x43, 0x1f, 0x11}}, + "Medical Service"}, + {{0x2fc28df6,{0xe806, 0x436e, 0xe0b9}, {0x46, 0x1d, 0xeb, 0xad, 0x56, 0x60}}, + "Home Furnishings"}, + {{0x910313db,{0xafce, 0x4019, 0x1aa4}, {0xe6, 0x2c, 0xe6, 0xd1, 0xfd, 0xf7}}, + "Industrial"}, + {{0x9e442c6e,{0xe12a, 0x4407, 0xd68a}, {0x1c, 0x5e, 0x19, 0xe7, 0xfe, 0x01}}, + ""}, + {{0x37e2fe4a,{0xcd71, 0x413f, 0x0cad}, {0x81, 0xc5, 0x2c, 0xf4, 0x78, 0x79}}, + ""}, + {{0x3c756e09,{0xb2dc, 0x48a6, 0x04a9}, {0x20, 0xb7, 0xc9, 0x9d, 0x14, 0x51}}, + ""}, + {{0xa1245b1c,{0x156a, 0x48fc, 0x6f96}, {0xa5, 0xa3, 0x22, 0x54, 0x13, 0x97}}, + "Manufacturing"}, + {{0x5bddbd7a,{0xf3cb, 0x454c, 0x06af}, {0x46, 0x1a, 0x68, 0xea, 0x60, 0x1a}}, + "Note"}, + {{0xcb6777e1,{0xe0e0, 0x45ce, 0x309f}, {0x8d, 0x61, 0x7a, 0xd9, 0x89, 0xf5}}, + "City"}, + {{0xbc168c08,{0x2b7f, 0x44be, 0x3883}, {0x81, 0x31, 0x4a, 0x09, 0xf5, 0x78}}, + "Air Base"}, + {{0xa8857b0f,{0xfc3b, 0x4cd1, 0x9e91}, {0xf5, 0x3b, 0x21, 0xa8, 0x3b, 0xb9}}, + "Battlefield"}, + {{0x06db55c1,{0xf687, 0x4840, 0x7c80}, {0x95, 0x58, 0x77, 0x8e, 0x5a, 0xdd}}, + "Mining"}, + {{0xcc61b277,{0xa48c, 0x445a, 0xd9b9}, {0xe5, 0x91, 0x36, 0x18, 0x4e, 0x09}}, + "Mountain"}, + {{0xfde13186,{0xb6cb, 0x4374, 0xc880}, {0x56, 0x99, 0xeb, 0x51, 0x68, 0x87}}, + "Capital"}, + {{0xb14d90d1,{0xd943, 0x40ff, 0x9fb7}, {0x9b, 0x92, 0xd1, 0x23, 0xca, 0xef}}, + "Route"}, + {{0x7eabc63f,{0x05d0, 0x4465, 0xb1b0}, {0x61, 0x2a, 0xf7, 0x4d, 0x0f, 0x4e}}, + "Overnight"}, + {{0xac39d8b9,{0xfcdc, 0x4b50, 0x9ca6}, {0xea, 0x6c, 0x4b, 0xb5, 0x96, 0x0f}}, + "Route End Active"}, + {{0xe1b9d86b,{0x95e6, 0x4bd8, 0xd880}, {0x7b, 0x6c, 0xc6, 0xd2, 0x00, 0x34}}, + "Route End Inactive"}, + {{0x98712315,{0x7e1e, 0x4024, 0x8392}, {0xe3, 0xb8, 0x5a, 0x51, 0x45, 0xb4}}, + "Fuel Stop"}, + {{0xe5ea5b38,{0x7b80, 0x4b42, 0x0aba}, {0x3d, 0x38, 0xf0, 0xe1, 0x17, 0x9a}}, + "Route Start Active"}, + {{0x18fd0d49,{0x0a29, 0x433a, 0xd584}, {0xe5, 0xb7, 0x5b, 0xe8, 0x25, 0xbc}}, + "Route Start Inactive"}, + {{0x2f52144b,{0x903e, 0x4dd9, 0x79af}, {0xe1, 0x66, 0x9b, 0xfc, 0xa9, 0xc1}}, + "Route Stop Active"}, + {{0xfaf8d826,{0xd27d, 0x4316, 0x0e92}, {0xce, 0x8d, 0x85, 0x93, 0x4c, 0xf5}}, + "Route Stop Inactive"}, + {{0xff44cae2,{0x707c, 0x4a1c, 0x43af}, {0x8b, 0xb6, 0xb1, 0x19, 0x9c, 0xf2}}, + "Route Via"}, + {{0x5a50d59b,{0xc15b, 0x49c4, 0x9faa}, {0xc4, 0x1c, 0x4f, 0xe2, 0x95, 0x2a}}, + "Radiation Green"}, + {{0x19556023,{0xb1e5, 0x4c9c, 0x49ba}, {0x08, 0x52, 0xa1, 0x24, 0x3d, 0x9f}}, + "Radiation Red"}, + {{0xa54be251,{0x6688, 0x49fb, 0x60b3}, {0x89, 0x56, 0x37, 0x68, 0xc5, 0xb0}}, + "Electricity"}, + {{0xd793ff0c,{0xfbe0, 0x4383, 0x3183}, {0xcf, 0x4f, 0x04, 0xb7, 0xee, 0x0a}}, + "Personal Furnishings"}, + {{0x00f90733,{0x7ab5, 0x42cf, 0x468c}, {0xbf, 0x91, 0x27, 0xd3, 0xa8, 0x9c}}, + "Personal Services"}, + {{0xea677f24,{0xbbe8, 0x4238, 0xee9c}, {0x6c, 0x0a, 0xec, 0x0e, 0x34, 0xf4}}, + "Telephone Black"}, + {{0x2d8a05b5,{0x8baf, 0x4f28, 0xf58b}, {0xfb, 0x7f, 0x37, 0x34, 0x28, 0xa7}}, + "Government Light"}, + {{0x40c64dfc,{0xc2d0, 0x4b0e, 0x6582}, {0x3f, 0x26, 0x9c, 0xcb, 0x6f, 0x1d}}, + "Airport Red Square"}, + {{0xf27adb5d,{0x3629, 0x44c7, 0x95a2}, {0x25, 0x2c, 0x95, 0x24, 0x98, 0x2f}}, + "Propeller Aircraft"}, + {{0x5a718e13,{0x3547, 0x42c5, 0x6d9d}, {0xb2, 0x82, 0xa5, 0x53, 0xbd, 0x3a}}, + "Jet Aircraft"}, + {{0x0a471039,{0x2dfe, 0x447e, 0x54be}, {0xa3, 0x93, 0xae, 0x9a, 0xdd, 0xac}}, + "Government"}, + {{0x4a59da2f,{0xe1c3, 0x42c3, 0x6ca1}, {0x06, 0xb9, 0x14, 0x1b, 0x89, 0x99}}, + "USA Regional"}, + {{0xf16500a9,{0xa845, 0x4293, 0xae89}, {0x5c, 0x29, 0xbb, 0x0d, 0x06, 0xf7}}, + "House 2"}, + {{0x7b05524d,{0xcb5a, 0x456f, 0x96b3}, {0x03, 0x61, 0x24, 0x54, 0x6a, 0x54}}, + "Picnic"}, + {{0xb88ad7a1,{0xb94d, 0x42e8, 0x2b9d}, {0xf5, 0x4c, 0x2b, 0xff, 0x57, 0xdc}}, + "Restaurant"}, + {{0xdc48a20a,{0x54a2, 0x4c61, 0x1fbe}, {0x02, 0x74, 0x5b, 0xe9, 0x18, 0x99}}, + "Store 2"}, + {{0x6b5ab040,{0x96df, 0x46ae, 0xacb8}, {0xe4, 0x47, 0x66, 0x3f, 0xec, 0x9b}}, + ""}, + {{0x153b2cff,{0x6232, 0x4294, 0xd59a}, {0xc5, 0xa0, 0x7b, 0xe0, 0x16, 0xeb}}, + "Blue Star"}, + {{0xf276f6b3,{0x586a, 0x4bf8, 0x2f82}, {0xf2, 0x69, 0xe3, 0x76, 0x7e, 0xd5}}, + ""}, + {{0x91d242c8,{0x0986, 0x4fad, 0x8286}, {0xec, 0x79, 0x79, 0xcd, 0xab, 0x02}}, + "Running"}, + {{0x8b0078db,{0x6ee0, 0x4caa, 0xd3b5}, {0xfe, 0xe1, 0xc2, 0xbf, 0x94, 0x7d}}, + "Transportation"}, + {{0x0599f6c9,{0x478e, 0x4f63, 0x78a5}, {0xed, 0x31, 0xb5, 0xae, 0xda, 0x89}}, + "Fishing"}, + {{0x7389128c,{0x0e78, 0x4d5d, 0x4189}, {0xb8, 0xf3, 0xb5, 0xbd, 0x70, 0xb1}}, + "Automotive"}, + {{0x0362b593,{0x3df6, 0x48ed, 0xc489}, {0x85, 0x13, 0xc1, 0xc0, 0xb9, 0x0d}}, + "Cloudy"}, + {{0xf0717a94,{0xd048, 0x4770, 0x9bab}, {0x80, 0x09, 0xbd, 0x4b, 0x1e, 0x75}}, + "Partly Cloudy"}, + {{0x14486bbc,{0xae6b, 0x44ea, 0xd6b9}, {0xbf, 0x9a, 0x39, 0x7a, 0x51, 0x6c}}, + "Mostly Cloudy"}, + {{0x7a258c70,{0xabec, 0x4cff, 0x4983}, {0x84, 0xdc, 0x2f, 0x2e, 0xff, 0x28}}, + "Tornado"}, + {{0xeff260d4,{0x46d5, 0x4fb5, 0xc79c}, {0x5e, 0x06, 0xc8, 0xab, 0x7a, 0x2b}}, + "Lightning"}, + {{0xc3d70220,{0x5154, 0x4766, 0xf0af}, {0xdf, 0x86, 0x74, 0x40, 0x5f, 0x8c}}, + "Rain"}, + {{0xf2dfbc91,{0x7ae6, 0x11d5, 0xf3ae}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Blue Flag"}, + {{0xf2dfbc92,{0x7ae6, 0x11d5, 0xf3ae}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Dark Blue Flag"}, + {{0xf2dfbc93,{0x7ae6, 0x11d5, 0xf3ae}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Brown Flag"}, + {{0xf2dfbc94,{0x7ae6, 0x11d5, 0xf3ae}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Yellow Flag"}, + {{0xf2dfbc95,{0x7ae6, 0x11d5, 0xf3ae}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Red Flag 2"}, + {{0xf2dfbc96,{0x7ae6, 0x11d5, 0xf3ae}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Dark Red Flag"}, + {{0xf2dfbc97,{0x7ae6, 0x11d5, 0xf3ae}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Dark Green Flag"}, + {{0xf2dfbc98,{0x7ae6, 0x11d5, 0xf3ae}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Green Flag"}, + {{0xf2dfbc99,{0x7ae6, 0x11d5, 0xf3ae}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Blue-Green Flag"}, + {{0xf2dfbc9a,{0x7ae6, 0x11d5, 0xf3ae}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Light Blue Flag"}, + {{0x623e1ee1,{0xaf27, 0x100f, 0x29bc}, {0x00, 0x50, 0x04, 0x02, 0xf5, 0x32}}, + "Dark Blue Map Pin"}, + {{0xf2dfbc9d,{0x7ae6, 0x11d5, 0xf3ae}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Blue Map Pin"}, + {{0xf2dfbc9e,{0x7ae6, 0x11d5, 0xf3ae}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Yellow Map Pin"}, + {{0xf2dfbc9f,{0x7ae6, 0x11d5, 0xf3ae}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Brown Map Pin"}, + {{0xf2dfbca0,{0x7ae6, 0x11d5, 0xf3ae}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Red Map Pin"}, + {{0xf2dfbca1,{0x7ae6, 0x11d5, 0xf3ae}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Dark Red Map Pin"}, + {{0xf2dfbca2,{0x7ae6, 0x11d5, 0xf3ae}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Green Map Pin"}, + {{0xf2dfbca3,{0x7ae6, 0x11d5, 0xf3ae}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Dark Green Map Pin"}, + {{0xf2dfbca4,{0x7ae6, 0x11d5, 0xf3ae}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Gray Map Pin"}, + {{0xf2dfbca5,{0x7ae6, 0x11d5, 0xf3ae}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Dark Gray Map Pin"}, + {{0xd1703de0,{0x5c45, 0x11d5, 0xb8ae}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Green Dot"}, + {{0xd1703de1,{0x5c45, 0x11d5, 0xb8ae}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Dark Green Dot"}, + {{0xd1703de2,{0x5c45, 0x11d5, 0xb8ae}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Blue Dot"}, + {{0xd1703de3,{0x5c45, 0x11d5, 0xb8ae}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Dark Blue Dot"}, + {{0xd1703de5,{0x5c45, 0x11d5, 0xb8ae}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Red Dot"}, + {{0x45c088e0,{0x672d, 0x11d5, 0xcbae}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Dark Red Dot"}, + {{0x45c088e1,{0x672d, 0x11d5, 0xcbae}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Yellow Dot"}, + {{0x45c088e2,{0x672d, 0x11d5, 0xcbae}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Brown Dot"}, + {{0x45c088e3,{0x672d, 0x11d5, 0xcbae}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Light Blue Dot"}, + {{0xbde3a8a1,{0x7aeb, 0x11d5, 0xf3ae}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Blue-Green Dot"}, + {{0xbde3a8a2,{0x7aeb, 0x11d5, 0xf3ae}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Small Green Dot"}, + {{0xbde3a8a3,{0x7aeb, 0x11d5, 0xf3ae}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Small Dark Green Dot"}, + {{0xbde3a8a4,{0x7aeb, 0x11d5, 0xf3ae}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Small Blue Dot"}, + {{0xbde3a8a5,{0x7aeb, 0x11d5, 0xf3ae}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Small Dark Blue Dot"}, + {{0xbde3a8a6,{0x7aeb, 0x11d5, 0xf3ae}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Small Red Dot"}, + {{0xbde3a8a7,{0x7aeb, 0x11d5, 0xf3ae}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Small Dark Red Dot"}, + {{0xbde3a8a8,{0x7aeb, 0x11d5, 0xf3ae}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Small Yellow Dot"}, + {{0xbde3a8a9,{0x7aeb, 0x11d5, 0xf3ae}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Small Brown Dot"}, + {{0xbde3a8aa,{0x7aeb, 0x11d5, 0xf3ae}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Small Light Blue Dot"}, + {{0xbde3a8ab,{0x7aeb, 0x11d5, 0xf3ae}, {0x00, 0x01, 0x02, 0x31, 0x5f, 0xfd}}, + "Small Blue-Green Dot"}, + {{0x623e1ee0,{0xaf27, 0x11d3, 0x29bc}, {0x00, 0x50, 0x04, 0x02, 0xf5, 0x32}}, + "Red Flag"}, + {{0x623e1ee1,{0xaf27, 0x11d3, 0x29bc}, {0x00, 0x50, 0x04, 0x02, 0xf5, 0x32}}, + "Map Pin"}, + {{0x623e1ee2,{0xaf27, 0x11d3, 0x29bc}, {0x00, 0x50, 0x04, 0x02, 0xf5, 0x32}}, + "Yellow Square"}, + {{0x623e1ee3,{0xaf27, 0x11d3, 0x29bc}, {0x00, 0x50, 0x04, 0x02, 0xf5, 0x32}}, + "Red X"}, + {{0x623e1ee4,{0xaf27, 0x11d3, 0x29bc}, {0x00, 0x50, 0x04, 0x02, 0xf5, 0x32}}, + "Blue Circle"}, + {{0x623e1ee5,{0xaf27, 0x11d3, 0x29bc}, {0x00, 0x50, 0x04, 0x02, 0xf5, 0x32}}, + "House"}, + {{0x623e1ee7,{0xaf27, 0x11d3, 0x29bc}, {0x00, 0x50, 0x04, 0x02, 0xf5, 0x32}}, + "Triangle"}, + {{0x623e1ee8,{0xaf27, 0x11d3, 0x29bc}, {0x00, 0x50, 0x04, 0x02, 0xf5, 0x32}}, + "Green Star"}, + {{0x9d277805,{0xe2f8, 0x4f43, 0x3f97}, {0x35, 0x0d, 0x40, 0xae, 0x5c, 0xd3}}, + "Geocache"}, + {{0xcb8aad04,{0xcc2d, 0x47f2, 0x428a}, {0x80, 0xf7, 0xd6, 0x68, 0xed, 0x32}}, + "Geocache Found"}, + {{0x7341c1f4,{0xdecd, 0x4d35, 0x45a5}, {0x52, 0x25, 0x5e, 0xbf, 0xe6, 0x51}}, + "Tent"}, + {{0x835b84e2,{0xf10c, 0x45cb, 0x958f}, {0x18, 0x3a, 0xc2, 0x2a, 0xe5, 0x28}}, + "Tipup Up"}, + {{0xce06fc92,{0xbb0c, 0x4ec1, 0xda93}, {0x64, 0x4a, 0x60, 0xbe, 0x40, 0x90}}, + "Topup Down"}, +}; + +int FindIconByName( const char *name, GUID *guid ) { + int i = 0; + for ( i = 0; i < (sizeof(default_guids)/sizeof(struct defguid)); i++ ) + { + if ( !case_ignore_strcmp(name, default_guids[i].name)) { + memcpy( guid, &(default_guids[i].guid), sizeof(GUID)); + return 1; + } + } + return 0; +} + +int FindIconByGuid( GUID *guid, char **name ) { + int i = 0; + for ( i = 0; i < (sizeof(default_guids)/sizeof(struct defguid)); i++ ) + { + if ( !memcmp(guid, &default_guids[i].guid, sizeof(GUID))) { + *name = default_guids[i].name; + return 1; + } + } + return 0; +} diff --git a/arcdist.c b/arcdist.c index 3fc13459a..800c45dd4 100644 --- a/arcdist.c +++ b/arcdist.c @@ -74,7 +74,12 @@ arcdist_process(void) fileline++; pound = strchr( line, '#' ); - if ( pound ) *pound = '\0'; + if ( pound ) { + if ( 0 == strncmp( pound, "#break", 6)) { + lat1 = lon1 = BADVAL; + } + *pound = '\0'; + } lat2 = lon2 = BADVAL; argsfound = sscanf( line, "%lf %lf", &lat2, &lon2 ); diff --git a/brauniger_iq.c b/brauniger_iq.c index 2d06c5753..e42d820c2 100644 --- a/brauniger_iq.c +++ b/brauniger_iq.c @@ -268,6 +268,7 @@ static arglist_t brauniger_iq_args[] = { ff_vecs_t brauniger_iq_vecs = { ff_type_serial, + FF_CAP_RW_ALL, rd_init, NULL, rd_deinit, diff --git a/cetus.c b/cetus.c index a85c9d487..6b09650d0 100644 --- a/cetus.c +++ b/cetus.c @@ -60,7 +60,7 @@ struct record { unsigned char sec; /* accuracy and precision information for use where applicable */ - char sat; /* ff if averaged or unknown */ + unsigned char sat; /* ff if averaged or unknown */ pdb_16 pdop; /* pdop * 100 */ pdb_16 hdop; pdb_16 vdop; @@ -165,7 +165,7 @@ data_read(void) for(pdb_rec = pdb->rec_index.rec; pdb_rec; pdb_rec=pdb_rec->next) { waypoint *wpt_tmp; - wpt_tmp = xcalloc(sizeof(*wpt_tmp),1); + wpt_tmp = waypt_new(); rec = (struct record *) pdb_rec->data; if ( be_read32(&rec->elevation) == -100000000 ) { @@ -238,13 +238,13 @@ cetus_writewpt(const waypoint *wpt) be_write16(&rec->year, 0xff); } - be_write32(&rec->longitude, wpt->longitude * 10000000.0); - be_write32(&rec->latitude, wpt->latitude * 10000000.0); + be_write32(&rec->longitude, (unsigned int) (wpt->longitude * 10000000.0)); + be_write32(&rec->latitude, (unsigned int) (wpt->latitude * 10000000.0)); if ( wpt->altitude == unknown_alt ) { - be_write32(&rec->elevation, -100000000U); + be_write32(&rec->elevation, -100000000); } else { - be_write32(&rec->elevation, wpt->altitude * 100.0); + be_write32(&rec->elevation, (unsigned int) (wpt->altitude * 100.0)); } be_write16( &rec->pdop, 0xffff ); @@ -327,7 +327,7 @@ cetus_writewpt(const waypoint *wpt) } vdata += strlen( vdata ) + 1; - opdb_rec = new_Record (0, 2, ct++, vdata-(char *)rec, (const ubyte *)rec); + opdb_rec = new_Record (0, 2, ct++, (uword) (vdata-(char *)rec), (const ubyte *)rec); if (opdb_rec == NULL) { fatal(MYNAME ": libpdb couldn't create record\n"); @@ -397,7 +397,7 @@ data_write(void) if (global_opts.synthesize_shortnames && waypointp->description) { if (waypointp->shortname) xfree(waypointp->shortname); - waypointp->shortname = mkshort(mkshort_wr_handle, waypointp->description); + waypointp->shortname = mkshort_from_wpt(mkshort_wr_handle, waypointp); } bh->wpt_name = waypointp->shortname; bh ++; @@ -416,6 +416,7 @@ data_write(void) ff_vecs_t cetus_vecs = { ff_type_file, + FF_CAP_RW_WPT, rd_init, wr_init, rd_deinit, diff --git a/chkdoc b/chkdoc index b3a409b70..19f93ed13 100644 --- a/chkdoc +++ b/chkdoc @@ -16,11 +16,12 @@ checkit() { ECODE=1 fi - if ! grep -qi "^ $TYPE$" README + if ! grep -qi "^ $TYPE$" ~/src/babelweb/README then echo $STY $TYPE is not documented in README. ECODE=1 fi + } ./gpsbabel -^ | @@ -39,5 +40,25 @@ do checkit $TYPE filter done +# +# See if they're in testo. +# +./gpsbabel -^2 | +while read FMT +do + set -- $FMT + case $1 in + file) + TYPE=$3 + if ! grep -qi "$TYPE" testo + then + echo $STY $TYPE is not in testo. + ECODE=1 + fi + + esac +done + + exit $ECODE diff --git a/coastexp.c b/coastexp.c new file mode 100644 index 000000000..faef555f5 --- /dev/null +++ b/coastexp.c @@ -0,0 +1,637 @@ +/* + Copyright (C) 2004 Justin Broughton, justinbr@earthlink.net + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + + */ + +#include "defs.h" +#if !NO_EXPAT +#include "xmlgeneric.h" +#include +static XML_Parser psr; +#endif +#include + +#include "uuid.h" + +FILE *fd; +FILE *ofd; + +#define MYNAME "coastexp" +#define MY_CBUF 4096 +#define MY_UBUF 128 +#define MY_TBUF 64 +#define MY_XBUF 128 + +#if NO_EXPAT +void +ce_rd_init(const char *fname) +{ + fatal(MYNAME ": This build excluded CoastalExplorer support because expat was not installed.\n"); +} + +void +ce_read(void) +{ +} +#else + +static char *element; // Current element being parsed +static char *cdatastr; // Current XML character data being built up (until a ) + +/* CE-specific mark structure - used for both route marks and standalone marks */ +struct CE_MARK { + queue Q; + char *id; // CE's mark ID (of the form "{}") + char *created; // CE's creation time (of the form "
TZ") + waypoint *wp; // GPSBabel waypoint + int used; // Is this mark used in a route or not? +}; +typedef struct CE_MARK ce_mark; + +/* CE-specific route structure */ +struct CE_ROUTE { + queue Q; + char *id; // CE's route ID (of the form "{}") + route_head *r; // GPSBabel route header + queue ce_mark_head; // list of CE marks in this route +}; +typedef struct CE_ROUTE ce_route; + +static queue ce_route_head; // List of routes currently found +static ce_route *currentRoute = NULL; // Current route being processed +static queue ce_mark_head; // List of stand-alone marks currently found +static ce_mark *currentMark = NULL; // Current mark being processed +static char *time_buffer = NULL; // Time buffer for processing times +static char *uuid_buffer = NULL; // UUID buffer for processing uuid's +static char *xml_buffer = NULL; // XML buffer for processing XML strings +static int inRoute = 0; // Are we processing a route? +static int inMark = 0; // Are we processing a mark? + +/* Add a route to the list of routes */ +static void +ce_add_route(ce_route *route) +{ + ENQUEUE_TAIL(&ce_route_head, &route->Q); +} + +/* Add a mark to the list of stand-alone marks */ +static void +ce_add_mark(ce_mark *mark) +{ + ENQUEUE_TAIL(&ce_mark_head, &mark->Q); +} + +/* Add a mark to the specified route */ +static void +ce_add_mark_to_route(ce_route *route, ce_mark *mark) +{ + ENQUEUE_TAIL(&route->ce_mark_head, &mark->Q); +} + +/* Free a mark */ +static void +ce_free_mark(ce_mark *mark) +{ + xfree(mark->id); + if (mark->created) + xfree(mark->created); + xfree(mark); +} + +/* Free a route */ +static void +ce_free_route(ce_route *route) +{ + queue *elem, *tmp; + QUEUE_FOR_EACH(&route->ce_mark_head, elem, tmp) { + ce_mark *mark = (ce_mark *) elem; + ce_free_mark(mark); + } + xfree(route->id); + xfree(route); + // Don't free the waypoint since this is done elsewhere +} + +/* Start processing an XML item */ +static void +ce_start(void *data, const char *el, const char **attr) +{ + const char **ap; + strcpy(element, el); + if (0 == strcmp(el, "Route")) { + inRoute = 1; + for (ap = attr; *ap; ap+=2) { + if (0 == strcmp(ap[0], "id")) { + // Create a CE route object and add it to the list of routes + currentRoute = (ce_route *) xcalloc(sizeof (ce_route), 1); + currentRoute->id=xstrdup(ap[1]); + if (doing_rtes) + currentRoute->r = route_head_alloc(); + QUEUE_INIT(¤tRoute->ce_mark_head); + if (doing_rtes) + ce_add_route(currentRoute); + } + } + } else if (0 == strcmp(el, "Mark")) { + inMark = 1; + currentMark = (ce_mark *) xcalloc(sizeof (ce_mark), 1); + currentMark->wp = NULL; + currentMark->used = 0; + ce_add_mark(currentMark); + for (ap = attr; *ap; ap+=2) { + if (0 == strcmp(ap[0], "id")) { + // Create a CE mark object and add it to the list of stand-alone marks + currentMark->id = xstrdup(ap[1]); + } + else if (0 == strcmp(ap[0], "created")) { + currentMark->created = xstrdup(ap[1]); + } + } + } +} + +/* Finish processing an XML item */ +static void +ce_end(void *data, const char *el) +{ + if (0 == strcmp(el, "Route")) { + if (!doing_rtes) + ce_free_route(currentRoute); + inRoute = 0; + } + else if (0 == strcmp(el, "Mark")) + inMark = 0; +} + +/* Process some XML character data for the current item */ +static void +ce_cdata(void *dta, const XML_Char *s, int len) +{ + if (*s != '\n') { + char *edatastr; + // We buffer up characters in 'cdatastr' until a single is received + if ((strlen(cdatastr) + len) > MY_CBUF) { + printf("Buffer overflow - line too long!"); + exit(-1); + } + edatastr = cdatastr+strlen(cdatastr); + memcpy(edatastr, s, len); + edatastr[len] = '\0'; + } else { + // Now process what we have in 'cdatastr' + s = cdatastr; + while (*s != '\0' && (*s == '\b' || *s == '\t')) + s++; + if (strlen(s) <= 0) + return; + if (0 == strcmp(element, "Marks")) { + if (inRoute) { + // We are processing the marks in a route so create a CE mark object + // and add it to the current route + ce_mark *mark = (ce_mark *) xcalloc(sizeof (ce_mark), 1); + mark->id = xstrdup(s); + mark->created = NULL; + mark->wp = NULL; + ce_add_mark_to_route(currentRoute, mark); + } + } else if (0 == strcmp(element, "Position")) { + if (inMark) { + // We are processing a standalone mark so read the lat/long position + // and create a waypoint to add to the current mark + char *position = xstrdup(s); + char *lat = position; + char *latNorS = position; + char *lng; + char *longEorW; + while (*latNorS != ' ') + latNorS++; + *latNorS++ = '\0'; + lng = latNorS; + lng++; lng++; + longEorW = lng; + while (*longEorW != ' ') + longEorW++; + *longEorW++ = '\0'; + if (!currentMark->wp) + currentMark->wp = waypt_new(); + currentMark->wp->latitude = atof(lat); + if (*latNorS == 'S') + currentMark->wp->latitude = -currentMark->wp->latitude; + currentMark->wp->longitude = atof(lng); + if (*longEorW == 'W') + currentMark->wp->longitude = -currentMark->wp->longitude; + xfree(position); + } + } else if (0 == strcmp(element, "Name")) { + // Names we care about may be either for routes or marks + if (inMark) + { + if (!currentMark->wp) + currentMark->wp = waypt_new(); + currentMark->wp->shortname = xstrdup(s); + + // Also set the creation time + if (currentMark->created) + { + struct tm t; + char yearString[5], monthString[3], dayString[3], hourString[3], minString[3], secString[3]; + memset(&t, 0, sizeof(struct tm)); + strncpy(yearString, currentMark->created, 4); + yearString[4] = '\0'; + t.tm_year = atoi(yearString) - 1900; + strncpy(monthString, currentMark->created+4, 2); + monthString[2] = '\0'; + t.tm_mon = atoi(monthString) - 1; + strncpy(dayString, currentMark->created+6, 2); + dayString[2] = '\0'; + t.tm_mday = atoi(dayString); + strncpy(hourString, currentMark->created+9, 2); + hourString[2] = '\0'; + t.tm_hour = atoi(hourString); + strncpy(minString, currentMark->created+11, 2); + minString[2] = '\0'; + t.tm_min = atoi(minString); + strncpy(secString, currentMark->created+13, 2); + secString[2] = '\0'; + t.tm_sec = atoi(secString); + currentMark->wp->creation_time = mktime(&t) + get_tz_offset(); + } + } + else if (inRoute) { + if (doing_rtes) + currentRoute->r->rte_name = xstrdup(s); + } + } else if (0 == strcmp(element, "Description")) { + // Descriptions we care about may be either for routes or marks + char *desc = xstrdup(s); + if (inMark) + { + if (!currentMark->wp) + currentMark->wp = waypt_new(); + currentMark->wp->description = desc; + } + else if (inRoute) + currentRoute->r->rte_desc = desc; + } + + // Start building a new string since we are done with this one + cdatastr[0] = '\0'; + } +} + +/* Set up reading the CE input file */ +void +ce_rd_init(const char *fname) +{ + fd = xfopen(fname, "r", MYNAME); + QUEUE_INIT(&ce_route_head); + QUEUE_INIT(&ce_mark_head); + + psr = XML_ParserCreate(NULL); + if (!psr) { + fatal(MYNAME ":Cannot create XML parser\n"); + } + + XML_SetElementHandler(psr, ce_start, ce_end); + cdatastr = xcalloc(MY_CBUF,1); + element = xcalloc(MY_CBUF,1); + XML_SetCharacterDataHandler(psr, ce_cdata); +} + +/* Parse the input file */ +void +ce_read(void) +{ + int len; + char buf[MY_CBUF]; + + while ((len = fread(buf, 1, sizeof(buf), fd))) { + if (!XML_Parse(psr, buf, len, feof(fd))) { + fatal(MYNAME ":Parse error at %d: %s\n", + XML_GetCurrentLineNumber(psr), + XML_ErrorString(XML_GetErrorCode(psr))); + } + } + + XML_ParserFree(psr); +} + +#endif + +/* Fix waypoints in route marks from the standalone marks */ +void +ce_fix_route_mark_waypoints(void) +{ + queue *elem, *tmp; + QUEUE_FOR_EACH(&ce_route_head, elem, tmp) { + ce_route *route = (ce_route *) elem; + queue *elem2, *tmp2; + QUEUE_FOR_EACH(&route->ce_mark_head, elem2, tmp2) { + ce_mark *mark = (ce_mark *) elem2; + queue *elem3, *tmp3; + QUEUE_FOR_EACH(&ce_mark_head, elem3, tmp3) { + ce_mark *mark2 = (ce_mark *) elem3; + if (0 == strcmp(mark->id, mark2->id)) { + mark->wp = waypt_dupe(mark2->wp); + mark2->used = 1; + break; + } + } + } + } +} + +/* Check route name and if NULL assign a name */ +void +ce_check_route_names(void) +{ + queue *elem, *tmp; + QUEUE_FOR_EACH(&ce_route_head, elem, tmp) { + ce_route *route = (ce_route *) elem; + if (route->r->rte_name == NULL) { + *cdatastr = '\0'; + strcat(cdatastr, ((ce_mark *) QUEUE_FIRST(&route->ce_mark_head))->wp->shortname); + strcat(cdatastr, "->"); + strcat(cdatastr, ((ce_mark *) QUEUE_LAST(&route->ce_mark_head))->wp->shortname); + route->r->rte_name = xstrdup(cdatastr); + } + } +} + +/* Remove marks used in routes */ +void +ce_remove_used_marks(void) +{ + queue *elem, *tmp; + QUEUE_FOR_EACH(&ce_mark_head, elem, tmp) { + ce_mark *mark = (ce_mark *) elem; + if (mark->used) + { + dequeue(elem); + if (mark->wp) + waypt_free(mark->wp); + ce_free_mark(mark); + } + } +} + +/* Print out results */ +void +ce_print_results(void) +{ + queue *elem, *tmp; + QUEUE_FOR_EACH(&ce_route_head, elem, tmp) { + queue *elem2, *tmp2; + ce_route *route = (ce_route *) elem; + printf("Route name=%s id=%s\n", route->r->rte_name, route->id); + QUEUE_FOR_EACH(&route->ce_mark_head, elem2, tmp2) { + ce_mark *mark = (ce_mark *) elem2; + if (mark->wp == NULL) + printf(" null\n"); + else + printf(" %s (%f, %f)\n", mark->wp->shortname, mark->wp->latitude, mark->wp->longitude); + } + } + + QUEUE_FOR_EACH(&ce_mark_head, elem, tmp) { + ce_mark *mark = (ce_mark *) elem; + printf("Mark name=%s id=%s ", mark->wp->shortname, mark->id); + if (mark->wp == NULL) + printf("(null)\n"); + else + printf("(%f, %f)\n", mark->wp->latitude, mark->wp->longitude); + } +} + +/* Finish reading the input file */ +void +ce_rd_deinit(void) +{ + /* If doing routes, we create GPSBabel route structures and waypoint structures for + any standalone waypoints. + If doing waypoints, we create only waypoint structures for both route waypoints and + standalone waypoints. + */ + queue *elem, *tmp; + + if (doing_rtes) { + ce_fix_route_mark_waypoints(); + ce_check_route_names(); + ce_remove_used_marks(); + } + + // Log results + if (global_opts.debug_level > 1) + ce_print_results(); + + // Add routes to GPSBabel + QUEUE_FOR_EACH(&ce_route_head, elem, tmp) { + ce_route *route = (ce_route *) elem; + if (doing_rtes) { + queue *elem2, *tmp2; + route_add_head(route->r); + QUEUE_FOR_EACH(&route->ce_mark_head, elem2, tmp2) { + ce_mark *mark = (ce_mark *) elem2; + if (mark->wp) + route_add_wpt(route->r, mark->wp); + else + printf("Undefined mark: %s\n", mark->id); + } + } + ce_free_route(route); + } + + // Add (unused) marks to GPSBabel + QUEUE_FOR_EACH(&ce_mark_head, elem, tmp) { + ce_mark *mark = (ce_mark *) elem; + waypt_add(mark->wp); + ce_free_mark(mark); + } + + fclose(fd); + xfree(element); + xfree(cdatastr); +} + +/* Setup for writing */ +void +ce_wr_init(const char *fname) +{ + QUEUE_INIT(&ce_mark_head); + + // Alloocate all buffers used for writing + time_buffer = xcalloc(MY_TBUF,1); + uuid_buffer = xcalloc(MY_UBUF,1); + xml_buffer = xcalloc(MY_XBUF, 1); + + ofd = xfopen(fname, "w", MYNAME); +} + +void +ce_wr_deinit(void) +{ + fclose(ofd); + + // Free the buffers used for writing + xfree(time_buffer); + xfree(uuid_buffer); + xfree(xml_buffer); +} + +/* Generate a CE-style creation time based on supplied time */ +static char * +ce_gen_creation_time(time_t tm) +{ + xml_fill_in_time(time_buffer, tm, XML_SHORT_TIME); + return time_buffer; +} + +/* Generate a CE-style creation time based on current time */ +static char * +ce_gen_current_time(void) +{ + return ce_gen_creation_time(current_time()); +} + +/* Generate a UUID (has same format as Microsoft registry GUIDs */ +static char * +ce_gen_uuid(void) +{ + uuid_t uu; + uuid_generate(uu); + sprintf(uuid_buffer, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", + uu[0], uu[1], uu[2], uu[3], uu[4], uu[5], uu[6], uu[7], + uu[8], uu[9], uu[10], uu[11], uu[12], uu[13], uu[14], uu[15]); + return uuid_buffer; +} + +/* Generate route header XML */ +static void +ce_route_hdr(const route_head *rte) +{ + if (doing_rtes) { + sprintf(xml_buffer, "{%s}", ce_gen_uuid()); + write_xml_entity_begin2(ofd, "\t", "Route", "created", ce_gen_current_time(), "id", xml_buffer); + write_xml_entity_begin0(ofd, "\t\t", "Marks"); + } +} + +/* Generate route body XML */ +static void +ce_route_disp(const waypoint *waypointp) +{ + char *uuid = ce_gen_uuid(); + char *id = xcalloc(strlen(uuid)+3, 1); + sprintf(id, "{%s}", uuid); + currentMark = (ce_mark *) xcalloc(sizeof (ce_mark), 1); + currentMark->id = id; + currentMark->wp = (waypoint *) waypointp; + ENQUEUE_TAIL(&ce_mark_head, ¤tMark->Q); + fprintf(ofd, "\t\t\t%s\n", id); // CE's departure from XML standard! +} + +/* Generate route trailer XML */ +static void +ce_route_tlr(const route_head *rte) +{ + if (doing_rtes) { + write_xml_entity_end(ofd, "\t\t", "Marks"); + write_optional_xml_entity(ofd, "\t\t", "Name", rte->rte_name); + write_xml_entity_end(ofd, "\t", "Route"); + } +} + +/* Generate waypoint body XML */ +static void +ce_waypt_pr(const waypoint *wp) +{ + double latitude = wp->latitude; + char NorS = 'N'; + char EorW = 'E'; + double longitude = wp->longitude; + + if (latitude < 0) { + latitude = -latitude; + NorS = 'S'; + } + if (longitude < 0) { + longitude = -longitude; + EorW = 'W'; + } + sprintf(xml_buffer, "%3.6f %c %3.6f %c", latitude, NorS, longitude, EorW); + write_xml_entity(ofd, "\t\t", "Position", xml_buffer); + write_optional_xml_entity(ofd, "\t\t", "Name", wp->shortname); +} + +/* Generate a standalone mark XML */ +static void +ce_mark_pr(const waypoint *wp) +{ + write_xml_entity_begin2(ofd, "\t", "Mark", + "created", ce_gen_creation_time(wp->creation_time), + "id", ce_gen_uuid()); + ce_waypt_pr(wp); + write_xml_entity_end(ofd, "\t", "Mark"); +} + +/* Generate all route marks */ +static void +ce_marks_pr(void) +{ + queue *elem, *tmp; + QUEUE_FOR_EACH(&ce_mark_head, elem, tmp) { + ce_mark *mark = (ce_mark *) elem; + ce_mark_pr(mark->wp); + ce_free_mark(mark); + } +} + +/* Write all routes and marks */ +void +ce_write(void) +{ + /* If doing routes, we write out the routes and all the standalone waypoints. + If doing waypoints, we write out the route waypoints (without the routes) and + the standalone waypoints. + */ + time_t now = 0; + now = current_time(); + + write_xml_header(ofd); + write_xml_entity_begin1(ofd, "", "NavObjectCollection", "created", + ce_gen_current_time()); + write_xml_entity(ofd, "\t", "Name", "Navigation Objects"); + + route_disp_all(ce_route_hdr, ce_route_tlr, ce_route_disp); + ce_marks_pr(); + waypt_disp_all(ce_mark_pr); + + write_xml_entity_end(ofd, "", "NavObjectCollection"); +} + +ff_vecs_t coastexp_vecs = { + ff_type_file, + { ff_cap_read|ff_cap_write, ff_cap_none, ff_cap_read|ff_cap_write }, + ce_rd_init, + ce_wr_init, + ce_rd_deinit, + ce_wr_deinit, + ce_read, + ce_write, + NULL, + NULL, +}; diff --git a/coldsync/pdb.c b/coldsync/pdb.c index d923e57f9..041b7f12c 100644 --- a/coldsync/pdb.c +++ b/coldsync/pdb.c @@ -6,7 +6,7 @@ * You may distribute this file under the terms of the Artistic * License, as specified in the README file. * - * $Id: pdb.c,v 1.6 2004/04/16 16:47:51 parkrrrr Exp $ + * $Id: pdb.c,v 1.7 2005/03/18 03:56:35 robertl Exp $ */ /* XXX - The way zero-length records are handled is a bit of a kludge. They * shouldn't normally exist, with the exception of expunged records. But, @@ -33,7 +33,9 @@ * but doesn't have it prototyped. Systems with 64-bit file I/O but * based on LP64 model (i.e. OS/X) _require_ the prototype for lseek. */ -#if !defined (__WIN32__) +#if defined (__WIN32__) +#include +#else #include #endif #include @@ -434,7 +436,7 @@ pdb_Write(const struct pdb *db, wptr = header_buf; memcpy(wptr, db->name, PDB_DBNAMELEN); wptr += PDB_DBNAMELEN; - put_uword(&wptr, (db->attributes & ~PDB_ATTR_OPEN)); + put_uword(&wptr, (uword) (db->attributes & ~PDB_ATTR_OPEN)); /* Clear the 'open' flag before writing */ put_uword(&wptr, db->version); put_udword(&wptr, db->ctime); @@ -1200,7 +1202,7 @@ get_file_length(int fd) /* And return to where we were before */ lseek(fd, here, SEEK_SET); - return eof - here; + return (uword) (eof - here); } /* pdb_LoadHeader @@ -1519,9 +1521,9 @@ pdb_LoadAppBlock(int fd, struct pdb *db) { int err; - localID next_off; /* Offset of the next thing in the file + udword next_off; /* Offset of the next thing in the file * after the AppInfo block */ - off_t offset; /* Offset into file, for checking */ + udword offset; /* Offset into file, for checking */ /* Check to see if there even *is* an AppInfo block */ if (db->appinfo_offset == 0L) @@ -1582,7 +1584,7 @@ pdb_LoadAppBlock(int fd, * we've already passed the beginning of the AppInfo block, as * given by its offset in the header. */ - offset = lseek(fd, 0L, SEEK_CUR); /* Find out where we are */ + offset = (udword) lseek(fd, 0L, SEEK_CUR); /* Find out where we are */ if (offset != db->appinfo_offset) { if (offset > db->appinfo_offset) @@ -1638,7 +1640,7 @@ pdb_LoadSortBlock(int fd, int err; localID next_off; /* Offset of the next thing in the file * after the sort block */ - off_t offset; /* Offset into file, for checking */ + localID offset; /* Offset into file, for checking */ /* Check to see if there even *is* a sort block */ if (db->sortinfo_offset == 0L) @@ -1695,7 +1697,7 @@ pdb_LoadSortBlock(int fd, * we've already passed the beginning of the sort block, as given * by its offset in the header. */ - offset = lseek(fd, 0L, SEEK_CUR); /* Find out where we are */ + offset = (udword) lseek(fd, 0L, SEEK_CUR); /* Find out where we are */ if (offset != db->sortinfo_offset) { if (offset > db->sortinfo_offset) @@ -1755,7 +1757,7 @@ pdb_LoadResources(int fd, i < db->numrecs; i++, rsrc = rsrc->next) { - off_t offset; /* Current offset, for checking */ + udword offset; /* Current offset, for checking */ udword next_off; /* Offset of next resource in file */ /* Sanity check: make sure we haven't stepped off the end @@ -1785,7 +1787,7 @@ pdb_LoadResources(int fd, * whether we've already passed the beginning of the * resource, as given by its offset in the resource index. */ - offset = lseek(fd, 0L, SEEK_CUR); + offset = (udword) lseek(fd, 0L, SEEK_CUR); /* Find out where we are now */ if (offset != rsrc->offset) { @@ -1843,7 +1845,7 @@ pdb_LoadResources(int fd, /* Subtract this resource's index from that of the next * thing, to get the size of this resource. */ - rsrc->data_len = next_off - rsrc->offset; + rsrc->data_len = (uword) (next_off - rsrc->offset); /* Allocate space for this resource */ if ((rsrc->data = (ubyte *) malloc(rsrc->data_len)) == NULL) @@ -1893,7 +1895,7 @@ pdb_LoadRecords(int fd, i < db->numrecs; i++, rec = rec->next) { - off_t offset; /* Current offset, for checking */ + udword offset; /* Current offset, for checking */ localID next_off; /* Offset of next resource in file */ /* Sanity check: make sure we haven't stepped off the end @@ -1918,7 +1920,7 @@ pdb_LoadRecords(int fd, * whether we've already passed the beginning of the * record, as given by its offset in the record index. */ - offset = lseek(fd, 0L, SEEK_CUR); + offset = (udword) lseek(fd, 0L, SEEK_CUR); /* Find out where we are now */ if (offset != rec->offset) { @@ -1975,7 +1977,7 @@ pdb_LoadRecords(int fd, /* Subtract this record's index from that of the next one, * to get the size of this record. */ - rec->data_len = next_off - rec->offset; + rec->data_len = (uword) (next_off - rec->offset); /* Allocate space for this record * If there's a record with length zero, don't pass that to diff --git a/coldsync/util.c b/coldsync/util.c index 984e22b74..61be647fb 100644 --- a/coldsync/util.c +++ b/coldsync/util.c @@ -12,7 +12,7 @@ * native format, convert them to Palm (big-endian) format, and write * them to a ubyte string. * - * $Id: util.c,v 1.3 2004/01/18 01:24:41 robertl Exp $ + * $Id: util.c,v 1.4 2005/03/18 03:56:35 robertl Exp $ */ #include "config.h" @@ -65,7 +65,7 @@ get_ubyte(const ubyte **buf) } INLINE void -put_ubyte(ubyte **buf, ubyte value) +put_ubyte(ubyte **buf, const ubyte value) { **buf = value; ++(*buf); @@ -83,7 +83,7 @@ get_uword(const ubyte **buf) } INLINE void -put_uword(ubyte **buf, uword value) +put_uword(ubyte **buf, const uword value) { **buf = (value >> 8) & 0xff; ++(*buf); @@ -103,15 +103,15 @@ get_udword(const ubyte **buf) } INLINE void -put_udword(ubyte **buf, udword value) +put_udword(ubyte **buf, const udword value) { - **buf = (value >> 24) & 0xff; + **buf = (ubyte) ((value >> 24) & 0xff); ++(*buf); - **buf = (value >> 16) & 0xff; + **buf = (ubyte) ((value >> 16) & 0xff); ++(*buf); - **buf = (value >> 8) & 0xff; + **buf = (ubyte) ((value >> 8) & 0xff); ++(*buf); - **buf = value & 0xff; + **buf = (ubyte) (value & 0xff); ++(*buf); } #if TIME diff --git a/copilot.c b/copilot.c index 10d028da4..787e5be43 100644 --- a/copilot.c +++ b/copilot.c @@ -88,7 +88,7 @@ data_read(void) waypoint *wpt_tmp; char *vdata; - wpt_tmp = xcalloc(sizeof(*wpt_tmp),1); + wpt_tmp = waypt_new(); rec = (struct record *) pdb_rec->data; wpt_tmp->longitude = @@ -158,7 +158,7 @@ copilot_writewpt(const waypoint *wpt) } vdata += strlen( vdata ) + 1; - opdb_rec = new_Record (0, 2, ct++, vdata-(char *)rec, (const ubyte *)rec); + opdb_rec = new_Record (0, 2, ct++, (uword) (vdata-(char *)rec), (const ubyte *)rec); if (opdb_rec == NULL) { fatal(MYNAME ": libpdb couldn't create record\n"); @@ -193,6 +193,7 @@ data_write(void) ff_vecs_t copilot_vecs = { ff_type_file, + FF_CAP_RW_WPT, rd_init, wr_init, rd_deinit, diff --git a/csv_util.c b/csv_util.c index 4d426382c..e2423a5b1 100644 --- a/csv_util.c +++ b/csv_util.c @@ -2,6 +2,7 @@ Utilities for parsing Character Separated Value files (CSV) Copyright (C) 2002 Alex Mottram (geo_alexm at cox-internet.com) + Copyright (C) 2002-2005 Robert Lipe This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -39,6 +40,11 @@ extern char *xcsv_urlbase; extern char *prefer_shortnames; +extern const char *gs_get_container(geocache_container t); +extern geocache_container gs_mktype(const char *t); +extern geocache_container gs_mkcont(const char *t); +extern const char *gs_get_cachetype(geocache_type t); + static double pathdist = 0; static double oldlon = 999; static double oldlat = 999; @@ -77,14 +83,13 @@ csv_stringclean(const char *string, const char *chararray) while (*p1) { if (*cp == *p1) { /* we don't want this character! */ - strncpy(p1, p1 + 1, (p2 - p1)); + memmove(p1, p1 + 1, (p2 - p1)); p1[p2 - p1] = '\0'; } p1++; } cp++; } - return (tmp); } @@ -146,7 +151,8 @@ csv_stringtrim(const char *string, const char *enclosure, int strip_max) } /* copy what's left over back into tmp. */ - strncpy(tmp, p1, (p2 - p1) + 1); + memmove(tmp, p1, (p2 - p1) + 1); + tmp[(p2 - p1) + 1] = '\0'; return (tmp); @@ -322,16 +328,19 @@ decdir_to_dec(const char * decdir) * human_to_dec() - convert a "human-readable" lat and/or lon to decimal * usage: human_to_dec( "N 41° 09.12' W 085° 09.36'", &lat, &lon ); * human_to_dec( "41 9 5.652 N", &lat, &lon ); + * + * which: 0-no preference 1-prefer lat 2-prefer lon *****************************************************************************/ static void -human_to_dec( const char *instr, double *outlat, double *outlon ) +human_to_dec( const char *instr, double *outlat, double *outlon, int which ) { double unk[3] = {999,999,999}; double lat[3] = {999,999,999}; double lon[3] = {999,999,999}; int latsign = 0; int lonsign = 0; + int unksign = 1; const char *cur; double *numres = unk; @@ -388,6 +397,10 @@ human_to_dec( const char *instr, double *outlat, double *outlon ) numres[numind] = atof(cur); while (cur && *cur && strchr("1234567890.",*cur)) cur++; break; + case '-': + unksign = -1; + cur++; + break; default: if (numres[numind] != 999) { numind++; @@ -401,6 +414,17 @@ human_to_dec( const char *instr, double *outlat, double *outlon ) } } + if ( lat[0] == 999 && lon[0] == 999 ) { + if ( which == 1 ) { + lat[0] = unk[0]; lat[1] = unk[1]; lat[2] = unk[2]; + latsign = unksign; + } + else if ( which == 2 ) { + lon[0] = unk[0]; lon[1] = unk[1]; lon[2] = unk[2]; + lonsign = unksign; + } + } + if ( outlat ) { if ( lat[0] != 999 ) *outlat = lat[0]; if ( lat[1] != 999 ) *outlat += lat[1]/60.0; @@ -580,6 +604,37 @@ xcsv_epilogue_add(char *epilogue) xcsv_file.epilogue_lines++; } +static +time_t +yyyymmdd_to_time(const char *s) +{ + int t = atol(s); + struct tm tm; + + memset(&tm, 0, sizeof(tm)); + + tm.tm_mday = t % 100; + t = t / 100; + tm.tm_mon = t % 100 - 1; + t = t / 100; + tm.tm_year = t - 1900; + return mktime(&tm); +} + +static +long +time_to_yyyymmdd(time_t t) +{ + long b; + struct tm *tm = gmtime(&t); + + b = (1900 + tm->tm_year) * 10000 + + (1 + tm->tm_mon) * 100 + + tm->tm_mday; + + return b; +} + /*****************************************************************************/ /* xcsv_parse_val() - parse incoming data into the waypt structure. */ /* usage: xcsv_parse_val("-123.34", *waypt, *field_map) */ @@ -616,7 +671,7 @@ xcsv_parse_val(const char *s, waypoint *wpt, const field_map_t *fmp) } else if (strcmp(fmp->key, "ICON_DESCR") == 0) { wpt->icon_descr = csv_stringtrim(s, "", 0); - wpt->icon_descr_is_dynamic = 1; + wpt->wpt_flags.icon_descr_is_dynamic = 1; } else /* LATITUDE CONVERSIONS**************************************************/ @@ -631,10 +686,10 @@ xcsv_parse_val(const char *s, waypoint *wpt, const field_map_t *fmp) } else if (strcmp(fmp->key, "LAT_INT32DEG") == 0) { /* latitude as a 32 bit integer offset */ - wpt->latitude = intdeg_to_dec(atof(s), 1); + wpt->latitude = intdeg_to_dec((int) atof(s), 1); } else if ( strcmp(fmp->key, "LAT_HUMAN_READABLE") == 0) { - human_to_dec( s, &wpt->latitude, &wpt->longitude ); + human_to_dec( s, &wpt->latitude, &wpt->longitude, 1 ); } else if ( strcmp(fmp->key, "LAT_NMEA") == 0) { wpt->latitude = ddmm2degrees(wpt->latitude); @@ -651,17 +706,17 @@ xcsv_parse_val(const char *s, waypoint *wpt, const field_map_t *fmp) } else if (strcmp(fmp->key, "LON_INT32DEG") == 0) { /* longitude as a 32 bit integer offset */ - wpt->longitude = intdeg_to_dec(atof(s), 0); + wpt->longitude = intdeg_to_dec((int) atof(s), 0); } else if ( strcmp(fmp->key, "LON_HUMAN_READABLE") == 0) { - human_to_dec( s, &wpt->latitude, &wpt->longitude ); + human_to_dec( s, &wpt->latitude, &wpt->longitude, 2 ); } else if ( strcmp(fmp->key, "LON_NMEA") == 0) { wpt->latitude = ddmm2degrees(wpt->longitude); } else /* LAT AND LON CONVERSIONS ********************************************/ if ( strcmp(fmp->key, "LATLON_HUMAN_READABLE") == 0) { - human_to_dec( s, &wpt->latitude, &wpt->longitude ); + human_to_dec( s, &wpt->latitude, &wpt->longitude, 0 ); } else /* DIRECTIONS **********************************************************/ if (strcmp(fmp->key, "LAT_DIR") == 0) { @@ -690,6 +745,12 @@ xcsv_parse_val(const char *s, waypoint *wpt, const field_map_t *fmp) /* Time as time_t */ wpt->creation_time = atol(s); } else + if (strcmp(fmp->key, "YYYYMMDD_TIME") == 0) { + wpt->creation_time = yyyymmdd_to_time(s); + } else + if (strcmp(fmp->key, "GEOCACHE_LAST_FOUND") == 0) { + wpt->gc_data.last_found = yyyymmdd_to_time(s); + } else /* GEOCACHING STUFF ***************************************************/ if (strcmp(fmp->key, "GEOCACHE_DIFF") == 0) { @@ -707,6 +768,14 @@ xcsv_parse_val(const char *s, waypoint *wpt, const field_map_t *fmp) if (strcmp(fmp->key, "GEOCACHE_CONTAINER") == 0) { wpt->gc_data.container = gs_mkcont(s); } else + if (strcmp(fmp->key, "GEOCACHE_HINT") == 0) { + wpt->gc_data.hint = csv_stringtrim(s, "", 0); + } else + if (strcmp(fmp->key, "GEOCACHE_PLACER") == 0) { + wpt->gc_data.placer = csv_stringtrim(s, "", 0); + } else + + /* OTHER STUFF ***************************************************/ if ( strcmp( fmp->key, "PATH_DISTANCE_MILES") == 0) { /* Ignored on input */ } else @@ -759,7 +828,7 @@ xcsv_data_read(void) } if (strlen(buff)) { - wpt_tmp = xcalloc(sizeof(*wpt_tmp), 1); + wpt_tmp = waypt_new(); s = buff; s = csv_lineparse(s, xcsv_file.field_delimiter, "", linecount); @@ -794,7 +863,7 @@ xcsv_data_read(void) } static void -xcsv_resetpathlen() +xcsv_resetpathlen(const route_head *head) { pathdist = 0; oldlat = 999; @@ -824,15 +893,15 @@ xcsv_waypt_pr(const waypoint *wpt) oldlon = wpt->longitude; oldlat = wpt->latitude; - if (strcmp(xcsv_file.field_delimiter, "\\w") == 0) + if (xcsv_file.field_delimiter && strcmp(xcsv_file.field_delimiter, "\\w") == 0) write_delimiter = " "; else write_delimiter = xcsv_file.field_delimiter; if ((! wpt->shortname) || (global_opts.synthesize_shortnames)) { if (wpt->description) { - if (global_opts.synthesize_shortnames) - shortname = mkshort(xcsv_file.mkshort_handle, wpt->description); + if (global_opts.synthesize_shortnames) + shortname = mkshort_from_wpt(xcsv_file.mkshort_handle, wpt); else shortname = csv_stringclean(wpt->description, xcsv_file.badchars); } else { @@ -856,10 +925,8 @@ xcsv_waypt_pr(const waypoint *wpt) if (description) { xfree(description); } - description = shortname; - } - - if (description) { + description = shortname; + } else if (description) { char *odesc = description; description = str_utf8_to_ascii(odesc); xfree(odesc); @@ -882,7 +949,12 @@ xcsv_waypt_pr(const waypoint *wpt) sprintf(buff, fmp->printfc, waypt_out_count + atoi(fmp->val)); } else if (strcmp(fmp->key, "CONSTANT") == 0) { - sprintf(buff, fmp->printfc, fmp->val); + const char *cp = xcsv_get_char_from_constant_table(fmp->val); + if (cp) { + sprintf(buff, fmp->printfc, cp); + } else { + sprintf(buff, fmp->printfc, fmp->val); + } } else if (strcmp(fmp->key, "SHORTNAME") == 0) { sprintf(buff, fmp->printfc, @@ -1043,6 +1115,12 @@ xcsv_waypt_pr(const waypoint *wpt) /* time as a time_t variable */ sprintf(buff, fmp->printfc, wpt->creation_time); } else + if (strcmp(fmp->key, "YYYYMMDD_TIME") == 0) { + sprintf(buff, fmp->printfc, time_to_yyyymmdd(wpt->creation_time)); + } else + if (strcmp(fmp->key, "GEOCACHE_LAST_FOUND") == 0) { + sprintf(buff, fmp->printfc, time_to_yyyymmdd(wpt->gc_data.last_found)); + } else /* GEOCACHE STUFF **************************************************/ if (strcmp(fmp->key, "GEOCACHE_DIFF") == 0) { @@ -1060,6 +1138,12 @@ xcsv_waypt_pr(const waypoint *wpt) if (strcmp(fmp->key, "GEOCACHE_TYPE") == 0) { /* Geocache Type */ sprintf(buff, fmp->printfc, gs_get_cachetype(wpt->gc_data.type)); + } else + if (strcmp(fmp->key, "GEOCACHE_HINT") == 0) { + sprintf(buff, fmp->printfc, NONULL(wpt->gc_data.hint)); + } else + if (strcmp(fmp->key, "GEOCACHE_PLACER") == 0) { + sprintf(buff, fmp->printfc, NONULL(wpt->gc_data.placer)); } else { /* this should probably never happen */ } @@ -1070,12 +1154,12 @@ xcsv_waypt_pr(const waypoint *wpt) fprintf (xcsv_file.xcsvfp, "%s", xcsv_file.record_delimiter); - if (shortname) - xfree(shortname); - if (description && description != shortname) xfree(description); + if (shortname) + xfree(shortname); + /* increment the index counter */ waypt_out_count++; } diff --git a/csv_util.h b/csv_util.h index e1e12cb16..a4d2d4210 100644 --- a/csv_util.h +++ b/csv_util.h @@ -62,6 +62,9 @@ xcsv_ofield_add(char *, char *, char *); void xcsv_destroy_style(void); +const char * +xcsv_get_char_from_constant_table(char *key); + /****************************************************************************/ /* types required for various xcsv functions */ /****************************************************************************/ diff --git a/defs.h b/defs.h index 21fa18ae2..4ac800dcb 100644 --- a/defs.h +++ b/defs.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002 Robert Lipe, robertlipe@usa.net + Copyright (C) 2002, 2003, 2004, 2005 Robert Lipe, robertlipe@usa.net This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -26,6 +26,7 @@ #include #include #include "queue.h" +#include "gbtypes.h" /* @@ -44,6 +45,11 @@ # define snprintf _snprintf #endif +/* Turn off numeric conversion warning */ +#if __WIN32__ +#pragma warning(disable:4244) +#endif + /* * Common definitions. There should be no protocol or file-specific * data in this file. @@ -81,11 +87,16 @@ typedef struct { unsigned int masked_objective; int verbose_status; /* set by GUI wrappers for status */ int no_smart_icons; + int no_smart_names; } global_options; extern global_options global_opts; extern const char gpsbabel_version[]; +/* Short or Long XML Times */ +#define XML_SHORT_TIME 1 +#define XML_LONG_TIME 2 + /* * Extended data if waypoint happens to represent a geocache. This is * totally voluntary data... @@ -99,7 +110,11 @@ typedef enum { gt_letterbox, gt_event, gt_suprise, - gt_webcam + gt_webcam, + gt_earth, + gt_locationless, + gt_benchmark, /* Extension to Groundspeak for GSAK */ + gt_cito } geocache_type; typedef enum { @@ -124,6 +139,8 @@ typedef struct { int diff; /* (multiplied by ten internally) */ int terr; /* (likewise) */ time_t exported; + time_t last_found; + char *placer; /* Placer name */ char *hint; /* all these UTF8, XML entities removed, May be not HTML. */ utf_string desc_short; utf_string desc_long; @@ -141,12 +158,28 @@ typedef struct xml_tag { struct xml_tag *child; } xml_tag ; +typedef void (*an1_destroy)(void *); +typedef void (*an1_copy)(void **, void *); +typedef struct { + an1_destroy destroy; + an1_copy copy; +} an1_base; + +/* + * Misc bitfields inside struct waypoint; + */ +typedef struct { + unsigned int icon_descr_is_dynamic:1; + unsigned int shortname_is_synthetic:1; +} wp_flags; + /* * This is a waypoint, as stored in the GPSR. It tries to not * cater to any specific model or protocol. Anything that needs to * be truncated, edited, or otherwise trimmed should be done on the * way to the target. */ + typedef struct { queue Q; /* Master waypoint q. Not for use by modules. */ @@ -191,7 +224,8 @@ typedef struct { char *notes; char *url; char *url_link_text; - int icon_descr_is_dynamic; + + wp_flags wpt_flags; const char *icon_descr; time_t creation_time; /* standardized in UTC/GMT */ int centiseconds; /* Optional hundredths of a second. */ @@ -203,11 +237,14 @@ typedef struct { * This causes it to be removed last. * This is currently used by the saroute input filter to give named * waypoints (representing turns) a higher priority. + * This is also used by the google input filter because they were + * nice enough to use exactly the same priority scheme. */ int route_priority; geocache_data gc_data; xml_tag *gpx_extras; + an1_base *an1_extras; void *extra_data; /* Extra data added by, say, a filter. */ } waypoint; @@ -218,6 +255,7 @@ typedef struct { char *rte_desc; int rte_num; int rte_waypt_ct; /* # waypoints in waypoint list */ + an1_base *an1_extras; } route_head; /* @@ -262,6 +300,7 @@ void waypt_compute_bounds(bounds *); void waypt_flush(queue *); void waypt_flush_all(void); unsigned int waypt_count(void); +void set_waypt_count(unsigned int nc); void free_gpx_extras (xml_tag * tag); void xcsv_setup_internal_style(const char *style_buf); void xcsv_read_internal_style(const char *style_buf); @@ -298,9 +337,11 @@ void *MKSHORT_NEW_HANDLE(DEBUG_PARAMS); #define mkshort( a, b) MKSHORT(a,b,__FILE__, __LINE__) #define mkshort_new_handle() MKSHORT_NEW_HANDLE(__FILE__,__LINE__) #endif +char *mkshort_from_wpt(void *h, const waypoint *wpt); void mkshort_del_handle(void *h); void setshort_length(void *, int n); void setshort_badchars(void *, const char *); +void setshort_goodchars(void *, const char *); void setshort_mustupper(void *, int n); void setshort_mustuniq(void *, int n); void setshort_whitespace_ok(void *, int n); @@ -318,15 +359,36 @@ void vmem_free(vmem_t*); void vmem_realloc(vmem_t*, size_t); -#define ARGTYPE_UNKNOWN 0 -#define ARGTYPE_INT 0x00000001 -#define ARGTYPE_FLOAT 0x00000002 -#define ARGTYPE_STRING 0x00000003 -#define ARGTYPE_BOOL 0x00000004 -#define ARGTYPE_FILE 0x00000005 -#define ARGTYPE_OUTFILE 0x00000006 -#define ARGTYPE_REQUIRED 0x40000000 -#define ARGTYPE_HIDDEN 0x20000000 +#define ARGTYPE_UNKNOWN 0x00000000 +#define ARGTYPE_INT 0x00000001 +#define ARGTYPE_FLOAT 0x00000002 +#define ARGTYPE_STRING 0x00000003 +#define ARGTYPE_BOOL 0x00000004 +#define ARGTYPE_FILE 0x00000005 +#define ARGTYPE_OUTFILE 0x00000006 + +/* REQUIRED means that the option is required to be set. + * See also BEGIN/END_REQ */ +#define ARGTYPE_REQUIRED 0x40000000 + +/* HIDDEN means that the option does not appear in help texts. Useful + * for debugging or testing options */ +#define ARGTYPE_HIDDEN 0x20000000 + +/* BEGIN/END_EXCL mark the beginning and end of an exclusive range of + * options. No more than one of the options in the range may be selected + * or set. If exactly one must be set, use with BEGIN/END_REQ + * Both of these flags set is just like neither set, so avoid doing that. */ +#define ARGTYPE_BEGIN_EXCL 0x10000000 +#define ARGTYPE_END_EXCL 0x08000000 + +/* BEGIN/END_REQ mark the beginning and end of a required range of + * options. One or more of the options in the range MUST be selected or set. + * If exactly one must be set, use with BEGIN/END_EXCL + * Both of these flags set is synonymous with REQUIRED, so use that instead + * for "groups" of exactly one option. */ +#define ARGTYPE_BEGIN_REQ 0x04000000 +#define ARGTYPE_END_REQ 0x02000000 #define ARGTYPE_TYPEMASK 0x00000fff #define ARGTYPE_FLAGMASK 0xfffff000 @@ -345,11 +407,29 @@ typedef enum { ff_type_serial, /* format describes a serial protoco (GUI can display port names) */ } ff_type; +typedef enum { + ff_cap_rw_wpt, + ff_cap_rw_trk, + ff_cap_rw_rte +} ff_cap_array; + +typedef enum { + ff_cap_none, + ff_cap_read = 1, + ff_cap_write = 2 +} ff_cap; +#define FF_CAP_RW_ALL \ + { ff_cap_read | ff_cap_write, ff_cap_read | ff_cap_write, ff_cap_read | ff_cap_write } + +#define FF_CAP_RW_WPT \ + { ff_cap_read | ff_cap_write, ff_cap_none, ff_cap_none} + /* * Describe the file format to the caller. */ typedef struct ff_vecs { ff_type type; + ff_cap cap[3]; ff_init rd_init; ff_init wr_init; ff_deinit rd_deinit; @@ -377,6 +457,7 @@ typedef struct filter_vecs { void waypt_init(void); void route_init(void); void waypt_disp(const waypoint *); +void waypt_status_disp(int total_ct, int myct); void fatal(const char *, ...) #if __GNUC__ __attribute__ ((__format__ (__printf__, 1, 2))) @@ -387,13 +468,13 @@ void warning(const char *, ...) __attribute__ ((__format__ (__printf__, 1, 2))) #endif ; -ff_vecs_t *find_vec(char *, char **); +ff_vecs_t *find_vec(char * const, char **); void disp_vecs(void); void exit_vecs(void); void disp_formats(int version); -void printposn(double c, int is_lat); +void printposn(const double c, int is_lat); -filter_vecs_t * find_filter_vec(char *, char **); +filter_vecs_t * find_filter_vec(char * const, char **); void free_filter_vec(filter_vecs_t *); void disp_filters(int version); void disp_filter_vecs(void); @@ -448,8 +529,10 @@ void xfprintf(const char *errtxt, FILE *stream, const char *format, ...); void xfputs(const char *errtxt, const char *s, FILE *stream); int case_ignore_strcmp(const char *s1, const char *s2); +int case_ignore_strncmp(const char *s1, const char *s2, int n); -char *strsub(char *s, char *search, char *replace); +char *strsub(const char *s, const char *search, const char *replace); +char *gstrsub(const char *s, const char *search, const char *replace); void rtrim(char *s); signed int get_tz_offset(void); time_t current_time(void); @@ -463,7 +546,7 @@ char * str_utf8_to_cp1252( const char * str ); char * str_utf8_to_ascii( const char * str ); /* this lives in gpx.c */ -time_t xml_parse_time( char *cdatastr ); +time_t xml_parse_time( const char *cdatastr ); xml_tag *xml_findfirst( xml_tag *root, char *tagname ); xml_tag *xml_findnext( xml_tag *root, xml_tag *cur, char *tagname ); diff --git a/delgpl.c b/delgpl.c index dd0146975..3e65936bf 100644 --- a/delgpl.c +++ b/delgpl.c @@ -46,7 +46,7 @@ gpl_rd_init(const char *fname) { gplfile_in = xfopen(fname, "rb", MYNAME); if (sizeof(struct gpl_point) != 56) { - fatal(MYNAME, ": gpl_point is %d instead of 56.\n", + fatal(MYNAME ": gpl_point is %d instead of 56.\n", sizeof(struct gpl_point)); } } @@ -56,7 +56,6 @@ gpl_read(void) { waypoint *wpt_tmp; route_head *track_head; - int br; gpl_point_t gp; double alt_feet; @@ -114,6 +113,7 @@ gpl_write(void) ff_vecs_t gpl_vecs = { ff_type_file, + { ff_cap_none, ff_cap_read | ff_cap_write, ff_cap_none }, gpl_rd_init, gpl_wr_init, gpl_rd_deinit, diff --git a/duplicate.c b/duplicate.c index 321834754..5556be28e 100644 --- a/duplicate.c +++ b/duplicate.c @@ -31,9 +31,9 @@ static char *correct_coords = NULL; static arglist_t dup_args[] = { {"shortname", &snopt, "Suppress duplicate waypoints based on name", - NULL, ARGTYPE_BOOL}, + NULL, ARGTYPE_BEGIN_REQ | ARGTYPE_BOOL}, {"location", &lcopt, "Suppress duplicate waypoint based on coords", - NULL, ARGTYPE_BOOL}, + NULL, ARGTYPE_END_REQ | ARGTYPE_BOOL}, {"all", &purge_duplicates, "Suppress all instances of duplicates", NULL, ARGTYPE_BOOL}, {"correct", &correct_coords, "Use coords from duplicate points", diff --git a/easygps.c b/easygps.c index 827d2057f..bcfab3f03 100644 --- a/easygps.c +++ b/easygps.c @@ -25,7 +25,7 @@ static FILE *file_in; static FILE *file_out; static void *mkshort_handle; -static char *deficon = NULL; +/* static char *deficon = NULL; */ #define MYNAME "EasyGPS" @@ -263,6 +263,7 @@ data_write(void) ff_vecs_t easygps_vecs = { ff_type_file, + FF_CAP_RW_WPT, rd_init, wr_init, rd_deinit, diff --git a/filter_vecs.c b/filter_vecs.c index f81c545b7..238d93e10 100644 --- a/filter_vecs.c +++ b/filter_vecs.c @@ -1,7 +1,7 @@ /* Describe vectors containing filter operations. - Copyright (C) 2002,2004 Robert Lipe, robertlipe@usa.net + Copyright (C) 2002,2004,2005 Robert Lipe, robertlipe@usa.net This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -198,6 +198,15 @@ disp_filter_vecs(void) } } +static signed int +alpha (const void *a, const void *b) +{ + const fl_vecs_t *const ap = a; + const fl_vecs_t *const bp = b; + + return strcasecmp(ap->desc , bp->desc); +} + /* * Display the available formats in a format that's easy to machine * parse. Typically invoked by programs like graphical wrappers to @@ -208,6 +217,12 @@ disp_filters(int version) { fl_vecs_t *vec; + qsort(filter_vec_list, + sizeof(filter_vec_list) / sizeof(filter_vec_list[0]) - 1, + sizeof(filter_vec_list[0]), + alpha); + + switch(version) { case 0: for (vec = filter_vec_list; vec->vec; vec++) { diff --git a/garmin.c b/garmin.c index 898fc59ac..a25b363c0 100644 --- a/garmin.c +++ b/garmin.c @@ -36,6 +36,9 @@ static char *getposn = NULL; static char *poweroff = NULL; static char *snlen = NULL; static char *snwhiteopt = NULL; +static char *deficon = NULL; +/* Technically, even this is a little loose as spaces arent allowed */ +static char valid_waypt_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789"; static arglist_t garmin_args[] = { @@ -43,6 +46,7 @@ arglist_t garmin_args[] = { ARGTYPE_INT }, { "snwhite", &snwhiteopt, "(0/1) Allow whitespace synth. shortnames", NULL, ARGTYPE_BOOL}, + { "deficon", &deficon, "Default icon name", NULL, ARGTYPE_STRING }, { "get_posn", &getposn, "Return current position as a waypoint", NULL, ARGTYPE_BOOL}, { "power_off", &poweroff, "Command unit to power itself down", @@ -125,6 +129,11 @@ rw_init(const char *fname) break; } + if (global_opts.debug_level > 0) { + fprintf(stderr, "Waypoint type: %d\n" + "Chosen waypoint length %d\n", + gps_waypt_type, short_length); + } /* * If the user provided a short_length, override the calculated value. */ @@ -136,6 +145,7 @@ rw_init(const char *fname) if (snwhiteopt) setshort_whitespace_ok(mkshort_handle, atoi(snwhiteopt)); + setshort_goodchars(mkshort_handle, valid_waypt_chars); setshort_mustupper(mkshort_handle, 1); } @@ -158,6 +168,7 @@ waypt_read_cb(int total_ct, GPS_PWay *way) i++; waypt_status_disp(total_ct, i); } + return 0; } static void @@ -212,6 +223,8 @@ waypt_read(void) } else { wpt_tmp->altitude = way[i]->alt; } + if (way[i]->Time_populated) + wpt_tmp->creation_time = way[i]->Time; waypt_add(wpt_tmp); GPS_Way_Del(&way[i]); @@ -233,7 +246,7 @@ track_read(void) ntracks = GPS_Command_Get_Track(portname, &array); - if ( ntracks == 0 ) + if ( ntracks <= 0 ) return; for(i = 0; i < ntracks; i++) { @@ -265,7 +278,6 @@ track_read(void) sprintf(trk_head->rte_name, "%s #%s", trk_name, trk_seg_num_buf); } trk_seg_num++; - trk_head->rte_num = trk_num; trk_num++; track_add_head(trk_head); } @@ -281,8 +293,8 @@ track_read(void) route_add_wpt(trk_head, wpt); } - while(--ntracks) { - GPS_Track_Del(&array[ntracks]); + while(ntracks) { + GPS_Track_Del(&array[--ntracks]); } xfree(array); } @@ -294,15 +306,13 @@ route_read(void) int32 nroutepts; int i; GPS_PWay *array; + route_head *rte_head; nroutepts = GPS_Command_Get_Route(portname, &array); - fprintf(stderr, "Routes %d\n", (int) nroutepts); +// fprintf(stderr, "Routes %d\n", (int) nroutepts); #if 1 for (i = 0; i < nroutepts; i++) { - route_head *rte_head; - waypoint * wpt_tmp; - if (array[i]->isrte) { char *csrc = NULL; /* What a horrible API has libjeeps for making this @@ -313,18 +323,16 @@ route_read(void) case 202: csrc = array[i]->rte_ident; break; default: break; } - rte_head = route_head_alloc(); - route_add_head(rte_head); - if (csrc) { - rte_head->rte_name = xstrdup(csrc); - } - ; - + rte_head = route_head_alloc(); + route_add_head(rte_head); + if (csrc) { + rte_head->rte_name = xstrdup(csrc); + } } else { if (array[i]->islink) { continue; } else { - wpt_tmp = xcalloc(sizeof (*wpt_tmp), 1); + waypoint *wpt_tmp = xcalloc(sizeof (*wpt_tmp), 1); wpt_tmp->latitude = array[i]->lat; wpt_tmp->longitude = array[i]->lon; wpt_tmp->shortname = array[i]->ident; @@ -378,7 +386,7 @@ sane_GPS_Way_New(void) way->addr[0] = 0; way->cross_road[0] = 0; way->cross_road[0] = 0; - way->dpth = 1.0e25; + way->dpth = 1.0e25f; way->wpt_class = 0; return way; @@ -397,6 +405,23 @@ waypt_write_cb(GPS_PWay *way) return 0; } +/* + * If we're not using smart icons, try to put the cache info in the + * description. + */ +const char * +get_gc_info(waypoint *wpt) +{ + if (global_opts.no_smart_icons) { + if (wpt->gc_data.type == gt_virtual) return "V "; + if (wpt->gc_data.type == gt_unknown) return "? "; + if (wpt->gc_data.type == gt_multi) return "Mlt "; + if (wpt->gc_data.container == gc_micro) return "M "; + if (wpt->gc_data.container == gc_small) return "S "; + } + return ""; +} + static void waypoint_write(void) { @@ -406,7 +431,6 @@ waypoint_write(void) queue *elem, *tmp; extern queue waypt_head; GPS_PWay *way; - extern int32 gps_save_id; int icon; way = xcalloc(n,sizeof(*way)); @@ -428,21 +452,28 @@ waypoint_write(void) if(wpt->description) src = wpt->description; if(wpt->notes) src = wpt->notes; - ident = global_opts.synthesize_shortnames ? - mkshort(mkshort_handle, src) : - wpt->shortname; + /* + * mkshort will do collision detection and namespace + * cleaning + */ + ident = mkshort(mkshort_handle, + global_opts.synthesize_shortnames ? src : + wpt->shortname); /* Should not be a strcpy as 'ident' isn't really a C string, * but rather a garmin "fixed length" buffer that's padded * to the end with spaces. So this is NOT (strlen+1). */ memcpy(way[i]->ident, ident, strlen(ident)); + if (global_opts.synthesize_shortnames) { xfree(ident); } way[i]->ident[sizeof(way[i]->ident)-1] = 0; - if (wpt->gc_data.diff && wpt->gc_data.terr) { - snprintf(obuf, sizeof(obuf), "%d/%d %s", + if (!global_opts.no_smart_icons && + wpt->gc_data.diff && wpt->gc_data.terr) { + snprintf(obuf, sizeof(obuf), "%s%d/%d %s", + get_gc_info(wpt), wpt->gc_data.diff, wpt->gc_data.terr, src); memcpy(way[i]->cmnt, obuf, strlen(obuf)); @@ -452,10 +483,14 @@ waypoint_write(void) way[i]->lon = wpt->longitude; way[i]->lat = wpt->latitude; - if (get_cache_icon(wpt)) { - icon = mps_find_icon_number_from_desc(get_cache_icon(wpt), PCX); + if (deficon) { + icon = mps_find_icon_number_from_desc(deficon, PCX); } else { - icon = mps_find_icon_number_from_desc(wpt->icon_descr, PCX); + if (get_cache_icon(wpt)) { + icon = mps_find_icon_number_from_desc(get_cache_icon(wpt), PCX); + } else { + icon = mps_find_icon_number_from_desc(wpt->icon_descr, PCX); + } } /* For units that support tiny numbers of waypoints, just @@ -470,6 +505,7 @@ waypoint_write(void) } else { way[i]->alt = wpt->altitude; } + way[i]->Time = wpt->creation_time; i++; } @@ -586,7 +622,6 @@ track_write(void) tx_tracklist = xcalloc(n, sizeof(GPS_PTrack)); cur_tx_tracklist_entry = tx_tracklist; - for (i = 0; i < n; i++) { tx_tracklist[i] = GPS_Track_New(); } @@ -602,7 +637,7 @@ track_write(void) } static void -data_write() +data_write(void) { if (poweroff) { return; @@ -619,6 +654,7 @@ data_write() ff_vecs_t garmin_vecs = { ff_type_serial, + FF_CAP_RW_ALL, rw_init, rw_init, rw_deinit, diff --git a/garmin_tables.c b/garmin_tables.c index f7bd4ff24..f0d979083 100644 --- a/garmin_tables.c +++ b/garmin_tables.c @@ -48,6 +48,7 @@ icon_mapping_t garmin_icon_table[] = { { 71, 8200, "City (Large)" }, { 70, 8199, "City (Medium)" }, { 69, 8198, "City (Small)" }, + { 69, 8198, "Small City" }, { 97, 8237, "Civil" }, { 119, 8262, "Contact, Afro" }, { 120, 8272, "Contact, Alien" }, @@ -179,30 +180,30 @@ icon_mapping_t garmin_icon_table[] = { * numbers "-2" to signify that as a problem until we can create * these in a .mps or .gdb file and see their representation there. */ - { -2, 7680, "Custom 1" }, - { -2, 7681, "Custom 2" }, - { -2, 7682, "Custom 3" }, - { -2, 7683, "Custom 4" }, - { -2, 7684, "Custom 5" }, - { -2, 7685, "Custom 6" }, - { -2, 7686, "Custom 7" }, - { -2, 7687, "Custom 8" }, - { -2, 7688, "Custom 9" }, - { -2, 7689, "Custom 10" }, - { -2, 7690, "Custom 11" }, - { -2, 7691, "Custom 12" }, - { -2, 7692, "Custom 13" }, - { -2, 7693, "Custom 14" }, - { -2, 7694, "Custom 15" }, - { -2, 7695, "Custom 16" }, - { -2, 7696, "Custom 17" }, - { -2, 7697, "Custom 18" }, - { -2, 7698, "Custom 19" }, - { -2, 7799, "Custom 20" }, - { -2, 7700, "Custom 21" }, - { -2, 7701, "Custom 22" }, - { -2, 7702, "Custom 23" }, - { -2, 7703, "Custom 24" }, + { -2, 7680, "Custom 0" }, + { -2, 7681, "Custom 1" }, + { -2, 7682, "Custom 2" }, + { -2, 7683, "Custom 3" }, + { -2, 7684, "Custom 4" }, + { -2, 7685, "Custom 5" }, + { -2, 7686, "Custom 6" }, + { -2, 7687, "Custom 7" }, + { -2, 7688, "Custom 8" }, + { -2, 7689, "Custom 9" }, + { -2, 7690, "Custom 10" }, + { -2, 7691, "Custom 11" }, + { -2, 7692, "Custom 12" }, + { -2, 7693, "Custom 13" }, + { -2, 7694, "Custom 14" }, + { -2, 7695, "Custom 15" }, + { -2, 7696, "Custom 16" }, + { -2, 7697, "Custom 17" }, + { -2, 7698, "Custom 18" }, + { -2, 7699, "Custom 19" }, + { -2, 7700, "Custom 20" }, + { -2, 7701, "Custom 21" }, + { -2, 7702, "Custom 22" }, + { -2, 7703, "Custom 23" }, { 92, 8227, "Micro-Cache" }, /* icon for "Toll Booth" */ { 48, 161, "Virtual cache" }, /* icon for "Scenic Area" */ @@ -213,5 +214,30 @@ icon_mapping_t garmin_icon_table[] = { { 47, 160, "Event Cache" }, /* Icon for "Event" */ { 90, 8221, "Webcam Cache" }, /* Icon for "Live Theatre" */ + /* MapSource V6.x */ + + { 140, 8286, "Flag, Red" }, + { 141, 8284, "Flag, Blue" }, + { 142, 8285, "Flag, Green" }, + { 143, 8289, "Pin, Red" }, + { 144, 8287, "Pin, Blue" }, + { 145, 8288, "Pin, Green" }, + { 146, 8292, "Diamond, Red" }, + { 147, 8290, "Diamond, Blue" }, + { 148, 8291, "Diamond, Green" }, + { 149, 8293, "Bike Trail" }, + { 150, 181, "Fishing Hot Spot Facility" }, + { 151, 8249, "Police Station"}, + { 152, 8251, "Ski Resort" }, + { 153, 8252, "Ice Skating" }, + { 154, 8253, "Wrecker" }, + { 155, 184, "Anchor Prohibited" }, + { 156, 185, "Beacon" }, + { 157, 186, "Coast Guard" }, + { 158, 187, "Reef" }, + { 159, 188, "Weed Bed" }, + { 160, 189, "Dropoff" }, + { 161, 190, "Dock" }, + { -1, -1, NULL }, }; diff --git a/gbtypes.h b/gbtypes.h new file mode 100644 index 000000000..bdbc8ce5f --- /dev/null +++ b/gbtypes.h @@ -0,0 +1,48 @@ +/* + Abstract fixed size data types. + + Copyright (C) 2005 Robert Lipe, robertlipe@usa.net + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + + */ + +/* + * If this is a problem and any interesting system doesn't have the C99-ism + * of we'll come up with something more clever that'll likely + * include a gross collection of __STDC_VERSION >= 199901L || __GNUC__ + */ + +#if defined(_MSC_VER) + +typedef unsigned long gbuint32; +typedef unsigned short gbuint16; +typedef long gbint32; +typedef short gbint16; + +#else + +# if defined (__FreeBSD__) +# include +# else +# include +# endif + +typedef uint32_t gbuint32; +typedef uint16_t gbuint16; +typedef int32_t gbint32; +typedef int16_t gbint16; + +#endif // defined(_MSC_VER) diff --git a/gcdb.c b/gcdb.c index bde86f8ef..8f9727736 100644 --- a/gcdb.c +++ b/gcdb.c @@ -293,7 +293,7 @@ gcdb_write_wpt(const waypoint *wpt) */ reclen = gcdb_add_to_rec(rec, NULL, 0, NULL); - opdb_rec = new_Record(0, 2, ct++, reclen, (const ubyte *)rec); + opdb_rec = new_Record(0, 2, ct++, (uword) reclen, (const ubyte *)rec); if (opdb_rec == NULL) { fatal(MYNAME ": libpdb couldn't create record\n"); @@ -331,6 +331,7 @@ data_write(void) ff_vecs_t gcdb_vecs = { ff_type_file, + FF_CAP_RW_WPT, rd_init, wr_init, rd_deinit, diff --git a/geo.c b/geo.c index 9e8eeca10..c8ace7244 100644 --- a/geo.c +++ b/geo.c @@ -17,18 +17,8 @@ */ #include "defs.h" -#if !NO_EXPAT -#include -static XML_Parser psr; -#endif +#include "xmlgeneric.h" -static int in_wpt; -static int in_name; -static int in_link; -static int in_type; -static int in_cdata; -static char *cdatastr; -static char *typestr; static char *deficon = NULL; static waypoint *wpt_tmp; @@ -57,185 +47,106 @@ geo_read(void) { } #else -static void -tag_coord(const char **attrv) -{ - const char **avp = &attrv[0]; - - - while (*avp) { - if (strcmp(avp[0], "lat") == 0) { - sscanf(avp[1], "%lf", - &wpt_tmp->latitude); - } - else if (strcmp(avp[0], "lon") == 0) { - sscanf(avp[1], "%lf", - &wpt_tmp->longitude); - } - avp+=2; - } + +static xg_callback wpt_s, wpt_e; +static xg_callback wpt_link_s, wpt_link; +static xg_callback wpt_name, wpt_name_s, wpt_type, wpt_coord; + +static +xg_tag_mapping loc_map[] = { + { wpt_s, cb_start, "/loc/waypoint" }, + { wpt_e, cb_end, "/loc/waypoint" }, + { wpt_name_s, cb_start, "/loc/waypoint/name" }, + { wpt_name, cb_cdata, "/loc/waypoint/name" }, + { wpt_type, cb_cdata, "/loc/waypoint/type" }, + { wpt_link_s, cb_start, "/loc/waypoint/link" }, + { wpt_link, cb_cdata, "/loc/waypoint/link" }, + { wpt_coord, cb_start, "/loc/waypoint/coord" }, + { NULL, 0, NULL } +}; + +void wpt_s(const char *args, const char **unused) +{ +// wpt_tmp = waypt_new(); + wpt_tmp = xcalloc(sizeof(*wpt_tmp), 1); } -static void -tag_name(const char **attrv) +void wpt_e(const char *args, const char **unused) { - const char **avp = &attrv[0]; - while (*avp) { - if (strcmp(avp[0], "id") == 0) { - wpt_tmp->shortname = xstrdup(avp[1]); - } - avp+=2; - } + waypt_add(wpt_tmp); } -static void -tag_type(const char **attrv) +void wpt_name_s(const char *args, const char **attrv) { - const char **avp = &attrv[0]; - while (*avp) { - if (strcmp(avp[0], "type") == 0) { - wpt_tmp->icon_descr = xstrdup(avp[1]); - } - avp+=2; - } + const char **avp = &attrv[0]; + while (*avp) { + if (0 == strcmp(avp[0], "id")) { + wpt_tmp->shortname = xstrdup(avp[1]); + } + avp+=2; + } } -static void -tag_link(const char **attrv) +void wpt_name(const char *args, const char **unused) { - const char **avp = &attrv[0]; - while (*avp) { - if (strcmp(avp[0], "text") == 0) { - wpt_tmp->url_link_text = xstrdup(avp[1]); - } - avp+=2; - } + if (args) wpt_tmp->description = xstrappend(wpt_tmp->description,args); } -static void -geo_start(void *data, const char *el, const char **attr) +void wpt_link_s(const char *args, const char **attrv) { - - if (in_wpt) { - if (strcmp(el, "ele") == 0) { - wpt_tmp->altitude = atoi(attr[1]); - } - else if (strcmp(el, "name") == 0) { - tag_name(attr); - } - else if (strcmp(el, "coord") == 0) { - tag_coord(attr); - } - else if (strcmp(el, "type") == 0) { - tag_type(attr); - } - } - - if (strcmp(el, "waypoint") == 0) { - wpt_tmp = xcalloc(sizeof(*wpt_tmp), 1); - in_wpt++; - } else if (strcmp(el, "name") == 0) { - in_name++; - } else if (strcmp(el, "type") == 0) { - tag_type(attr); - in_type++; - } else if (strcmp(el, "link") == 0) { - tag_link(attr); - in_link++; - } + const char **avp = &attrv[0]; + while (*avp) { + if (0 == strcmp(avp[0], "text")) { + wpt_tmp->url_link_text = xstrdup(avp[1]); + } + avp+=2; + } +} +void wpt_link(const char *args, const char **attrv) +{ + wpt_tmp->url = xstrdup(args); } -static void -geo_end(void *data, const char *el) +void wpt_type(const char *args, const char **unused) { - if (in_cdata) { - if (in_name) { - wpt_tmp->description = xstrdup(cdatastr); - } - if (in_link) { - wpt_tmp->url = xstrdup(cdatastr); - } - in_cdata--; - memset(cdatastr,0, MY_CBUF); - } - if (strcmp(el, "waypoint") == 0) { - waypt_add(wpt_tmp); - in_wpt--; - } - else if (strcmp(el, "name") == 0) { - in_name--; - } - else if (strcmp(el, "type") == 0) { - wpt_tmp->icon_descr_is_dynamic = 1; - wpt_tmp->icon_descr = xstrdup(typestr); - memset(typestr,0, MY_CBUF); - in_type--; - } - else if (strcmp(el, "link") == 0) { - in_link--; - } + wpt_tmp->wpt_flags.icon_descr_is_dynamic = 1; + wpt_tmp->icon_descr = xstrdup(args); } -static void -geo_cdata(void *dta, const XML_Char *s, int len) +void wpt_coord(const char *args, const char **attrv) { - char *estr; - if (in_name || in_link) { - estr = cdatastr + strlen(cdatastr); - memcpy(estr, s, len); - in_cdata++; - } - if (in_type) { - estr = typestr + strlen(typestr); - memcpy(estr, s, len); - } + const char **avp = &attrv[0]; + + while (*avp) { + if (strcmp(avp[0], "lat") == 0) { + sscanf(avp[1], "%lf", + &wpt_tmp->latitude); + } + else if (strcmp(avp[0], "lon") == 0) { + sscanf(avp[1], "%lf", + &wpt_tmp->longitude); + } + avp+=2; + } } void geo_rd_init(const char *fname) { - fd = xfopen(fname, "r", MYNAME); - - psr = XML_ParserCreate(NULL); - if (!psr) { - fatal(MYNAME ":Cannot create XML parser\n"); - } - - XML_SetElementHandler(psr, geo_start, geo_end); - cdatastr = xcalloc(MY_CBUF,1); - typestr = xcalloc(MY_CBUF,1); - XML_SetCharacterDataHandler(psr, geo_cdata); + xml_init(fname, loc_map); } void geo_read(void) { - int len; - char buf[MY_CBUF]; - - while ((len = fread(buf, 1, sizeof(buf), fd))) { - if (!XML_Parse(psr, buf, len, feof(fd))) { - fatal(MYNAME ":Parse error at %d: %s\n", - XML_GetCurrentLineNumber(psr), - XML_ErrorString(XML_GetErrorCode(psr))); - } - } - - XML_ParserFree(psr); + xml_read(); } - #endif void geo_rd_deinit(void) { - if ( cdatastr ) { - xfree(cdatastr); - } - if ( typestr ) { - xfree(typestr); - } - fclose(fd); + xml_deinit(); } void @@ -287,6 +198,7 @@ geo_write(void) ff_vecs_t geo_vecs = { ff_type_file, + FF_CAP_RW_WPT, geo_rd_init, geo_wr_init, geo_rd_deinit, diff --git a/geoniche.c b/geoniche.c index 60f955c70..7fb0d4a7d 100644 --- a/geoniche.c +++ b/geoniche.c @@ -43,7 +43,7 @@ arglist_t Args[] = { "Database name (filename)", NULL, ARGTYPE_STRING }, {"category", &Arg_category, "Category name (Cache)", NULL, ARGTYPE_STRING }, - {0, 0, 0, 0 } + {0, 0, 0, 0, 0 } }; #define ARG_FREE(X) do { if (X) { xfree(X); X = NULL; } } while (0) @@ -216,7 +216,7 @@ data_read(void) char gid[6+1]; struct tm tm; - wpt = xcalloc(sizeof(*wpt), 1); + wpt = waypt_new(); if (!wpt) fatal(MYNAME ": Couldn't allocate waypoint.\n"); vdata = (char *) pdb_rec->data; @@ -335,7 +335,7 @@ data_read(void) wpt->longitude = lon; wpt->altitude = alt; wpt->icon_descr = category; - wpt->icon_descr_is_dynamic = 1; + wpt->wpt_flags.icon_descr_is_dynamic = 1; if (gid[0]) { @@ -484,7 +484,7 @@ copilot_writewpt(const waypoint *wpt) fatal(MYNAME ": libpdb couldn't get record memory\n"); } - opdb_rec = new_Record (0, 0, ct++, vlen+1, vdata); + opdb_rec = new_Record (0, 0, ct++, (uword) (vlen+1), vdata); if (opdb_rec == NULL) fatal(MYNAME ": libpdb couldn't create record\n"); @@ -526,6 +526,7 @@ data_write(void) ff_vecs_t geoniche_vecs = { ff_type_file, + FF_CAP_RW_WPT, rd_init, wr_init, rd_deinit, diff --git a/glogbook.c b/glogbook.c new file mode 100644 index 000000000..3fe98162d --- /dev/null +++ b/glogbook.c @@ -0,0 +1,180 @@ +/* + Access Garmin Logbook (Forerunner/Foretracker) data files. + + Copyright (C) 2004 Robert Lipe, robertlipe@usa.net + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + + */ + +#include "defs.h" +#include "xmlgeneric.h" + +static FILE *ofd; +static waypoint *wpt_tmp; +static route_head *trk_head; + + +#define MYNAME "glogbook" + +static +arglist_t glogbook_args[] = { + {0, 0, 0, 0, 0} +}; + +/* Tracks */ +static xg_callback gl_trk_s; +// static xg_callback gl_trk_ident; +static xg_callback gl_trk_pnt_s, gl_trk_pnt_e; +static xg_callback gl_trk_utc; +static xg_callback gl_trk_lat; +static xg_callback gl_trk_long; +static xg_callback gl_trk_alt; + +static xg_tag_mapping gl_map[] = { + { gl_trk_s, cb_start, "/History/Run/Track" }, + { gl_trk_pnt_s,cb_start, "/History/Run/Track/Trackpoint/Position" }, + { gl_trk_pnt_e,cb_end, "/History/Run/Track/Trackpoint/Position" }, + { gl_trk_lat, cb_cdata, "/History/Run/Track/Trackpoint/Position/Latitude" }, + { gl_trk_long, cb_cdata, "/History/Run/Track/Trackpoint/Position/Longitude" }, + { gl_trk_alt, cb_cdata, "/History/Run/Track/Trackpoint/Position/Altitude" }, + { gl_trk_utc, cb_cdata, "/History/Run/Track/Trackpoint/Time" }, + { NULL, 0, NULL} +}; + +void +glogbook_rd_init(const char *fname) +{ + xml_init(fname, gl_map); +} + +void +glogbook_read(void) +{ + xml_read(); +} + +void +glogbook_rd_deinit(void) +{ + xml_deinit(); +} + +void +glogbook_wr_init(const char *fname) +{ + ofd = xfopen(fname, "w", MYNAME); +} + +void +glogbook_wr_deinit(void) +{ + fclose(ofd); +} + +static void +glogbook_waypt_pr(const waypoint *wpt) +{ + fprintf(ofd, "\n"); + fprintf(ofd, "\t\n"); + fprintf(ofd, "\t%f\n", wpt->latitude); + fprintf(ofd, "\t%f\n", wpt->longitude); + if (wpt->altitude != unknown_alt) { + fprintf(ofd, "\t%f\n", wpt->altitude); + } + xml_write_time(ofd, wpt->creation_time, "Time"); + fprintf(ofd, "\t\n"); + fprintf(ofd, "\n"); +} + +void +glogbook_hdr( const route_head *rte) +{ + fprintf(ofd, "\n"); +} + +void +glogbook_ftr(const route_head *rte) +{ + fprintf(ofd, "\n"); +} + +void +glogbook_write(void) +{ + fprintf(ofd, "\n"); + fprintf(ofd, "\n"); + track_disp_all(glogbook_hdr, glogbook_ftr, glogbook_waypt_pr); + fprintf(ofd, "\n"); + fprintf(ofd, "\n"); +} + +void gl_trk_s(const char *args, const char **unused) +{ + trk_head = route_head_alloc(); + track_add_head(trk_head); +} +#if 0 +void gl_trk_ident(const char *args, const char **unused) +{ + trk_head->rte_name = xstrdup(args); +} +#endif + +void gl_trk_pnt_s(const char *args, const char **unused) +{ + wpt_tmp = waypt_new(); +} + +void gl_trk_pnt_e(const char *args, const char **unused) +{ + route_add_wpt(trk_head, wpt_tmp); +} + +void gl_trk_utc(const char *args, const char **unused) +{ + wpt_tmp->creation_time = xml_parse_time(args); +} + +void gl_trk_lat(const char *args, const char **unused) +{ + wpt_tmp->latitude = atof(args); +} + +void gl_trk_long(const char *args, const char **unused) +{ + wpt_tmp->longitude = atof(args); +} + +void gl_trk_alt(const char *args, const char **unused) +{ + wpt_tmp->altitude = atof(args); +} + + + +ff_vecs_t glogbook_vecs = { + ff_type_file, + FF_CAP_RW_ALL, + glogbook_rd_init, + glogbook_wr_init, + glogbook_rd_deinit, + glogbook_wr_deinit, + glogbook_read, + glogbook_write, + NULL, + glogbook_args +}; + diff --git a/google.c b/google.c new file mode 100644 index 000000000..200f3d215 --- /dev/null +++ b/google.c @@ -0,0 +1,213 @@ +/* + Copyright (C) 2002 Robert Lipe, robertlipe@usa.net + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + + */ +#include "defs.h" +#include "xmlgeneric.h" + +static char *encoded_points = NULL; +static char *encoded_levels = NULL; +static char *script = NULL; + +FILE *fd; + +static int serial = 0; + +#define MYNAME "google" +#define MY_CBUF 4096 + +#if NO_EXPAT +void +google_rd_init(const char *fname) +{ + fatal(MYNAME ": This build excluded Google Maps support because expat was not installed.\n"); +} + +void +google_read(void) +{ +} +#else + +static xg_callback goog_points, goog_levels, goog_poly_e, goog_script; + +static +xg_tag_mapping google_map[] = { + { goog_points, cb_cdata, "/page/directions/polyline/points" }, + { goog_levels, cb_cdata, "/page/directions/polyline/levels" }, + { goog_poly_e, cb_end, "/page/directions/polyline" }, + { goog_script, cb_cdata, "/html/head/script" }, + { NULL, 0, NULL } +}; + +void goog_script( const char *args, const char **unused ) +{ + if (args) + { + if ( script ) + { + script = xstrappend( script, args ); + } + else + { + script = xstrdup( args ); + } + } +} + +void goog_points( const char *args, const char **unused ) +{ + if (args) + { + if ( encoded_points ) + { + encoded_points = xstrappend( encoded_points, args ); + } + else + { + encoded_points = xstrdup(args); + } + } +} + +void goog_levels( const char *args, const char **unused ) +{ + if (args) + { + if ( encoded_levels ) + { + encoded_levels = xstrappend( encoded_levels, args ); + } + else + { + encoded_levels = xstrdup(args); + } + } +} + +static long decode_goog64( char **str ) +{ + long result = 0; + unsigned char c = 0; + unsigned char shift = 0; + + do + { + c = (unsigned char)(*(*str)++)-'?'; + result |= (c & 31)<latitude = lat / 100000.0; + wpt_tmp->longitude = lon / 100000.0; + wpt_tmp->route_priority=level; + wpt_tmp->shortname = (char *) xmalloc(7); + sprintf( wpt_tmp->shortname, "\\%5.5x", serial++ ); + route_add_wpt(track_head, wpt_tmp); + } + } + + if ( encoded_points ) + { + xfree( encoded_points ); + encoded_points = NULL; + } + if ( encoded_levels ) + { + xfree( encoded_levels ); + encoded_levels = NULL; + } +} + +void +google_rd_init(const char *fname) +{ + xml_init(fname, google_map); +} + +void +google_read(void) +{ + xml_read(); + if ( script ) + { + char *xml = strchr( script, '\'' ); + char *end = NULL; + if ( xml ) { + xml++; + end = strrchr( xml, '\'' ); + if ( end ) { + *end = '\0'; + xml_deinit(); + xml_init( NULL, google_map ); + xml_readstring( xml ); + } + } + xfree( script ); + } +} +#endif + +void +google_rd_deinit(void) +{ + xml_deinit(); +} + +ff_vecs_t google_vecs = { + ff_type_file, + { ff_cap_none, ff_cap_read, ff_cap_none}, + google_rd_init, + NULL, + google_rd_deinit, + NULL, + google_read, + NULL, + NULL, + NULL +}; diff --git a/gpilots.c b/gpilots.c index 0a95644fb..6af407510 100644 --- a/gpilots.c +++ b/gpilots.c @@ -232,7 +232,11 @@ data_read(void) int lon; int sz; fi_t fi; - + int trk_num = 0; + int trk_seg_num = 1; + char trk_seg_num_buf[10]; + char *trk_name = ""; + wpt_tmp = waypt_new(); rec = (struct record *) pdb_rec->data; @@ -273,7 +277,7 @@ data_read(void) wpt_tmp->depth = fi.f; fi.i = le_read32(&rec->wpt.d108.dist); wpt_tmp->proximity = fi.f; - wpt_tmp->icon_descr_is_dynamic = 0; + wpt_tmp->wpt_flags.icon_descr_is_dynamic = 0; wpt_tmp->icon_descr = mps_find_desc_from_icon_number((rec->wpt.d108.smbl[1] << 8) + rec->wpt.d108.smbl[0], PCX); waypt_add(wpt_tmp); break; @@ -282,9 +286,7 @@ data_read(void) * CustomTrkHdr */ case 101: - track_head = route_head_alloc(); - track_add_head(track_head); - track_head->rte_name = xstrndup(rec->wpt.CustTrkHdr.name, sizeof(rec->wpt.CustTrkHdr.name)); + trk_name = rec->wpt.CustTrkHdr.name; sz = be_read16(&rec->wpt.CustTrkHdr.number); /* switch between custom track points and compact track points. @@ -294,7 +296,27 @@ data_read(void) case 102: tp_cust = (Custom_Trk_Point_Type *) ((char *) pdb_rec->data + sizeof(rec->header) + sizeof(rec->wpt.CustTrkHdr)); while (sz--) { + if ((int)(tp_cust->new_trk) == 1 || trk_seg_num == 1) { + /* + * Start a new track segment + */ + track_head = route_head_alloc(); + if (trk_seg_num == 1) { + track_head->rte_name = xstrdup(trk_name); + } else { + /* name in the form TRACKNAME #n */ + snprintf(trk_seg_num_buf, sizeof(trk_seg_num_buf), "%d", trk_seg_num); + track_head->rte_name = xmalloc(strlen(trk_name)+strlen(trk_seg_num_buf)+3); + sprintf(track_head->rte_name, "%s #%s", trk_name, trk_seg_num_buf); + } + trk_seg_num++; + track_head->rte_num = trk_num; + trk_num++; + track_add_head(track_head); + } + wpt_tmp = waypt_new(); + /* This is even more odd. * Track data is stored as big endian while * waypoint data is little endian!? @@ -318,6 +340,25 @@ data_read(void) case 104: tp_comp = (Compact_Trk_Point_Type *) ((char *) pdb_rec->data + sizeof(rec->header) + sizeof(rec->wpt.CustTrkHdr)); while (sz--) { + if ((int)(tp_comp->new_trk) == 1 || trk_seg_num == 1) { + /* + * Start a new track segment + */ + track_head = route_head_alloc(); + if (trk_seg_num == 1) { + track_head->rte_name = xstrdup(trk_name); + } else { + /* name in the form TRACKNAME #n */ + snprintf(trk_seg_num_buf, sizeof(trk_seg_num_buf), "%d", trk_seg_num); + track_head->rte_name = xmalloc(strlen(trk_name)+strlen(trk_seg_num_buf)+3); + sprintf(track_head->rte_name, "%s #%s", trk_name, trk_seg_num_buf); + } + trk_seg_num++; + track_head->rte_num = trk_num; + trk_num++; + track_add_head(track_head); + } + wpt_tmp = waypt_new(); lon = be_read32(&tp_comp->lon); lat = be_read32(&tp_comp->lat); @@ -364,7 +405,7 @@ my_write_wpt(const waypoint *wpt) le_write32(&rec->wpt.d103.lat, lat); le_write32(&rec->wpt.d103.lon, lon); - opdb_rec = new_Record(0, 0, ct++, vdata - (char *) rec, (const ubyte *) rec); + opdb_rec = new_Record(0, 0, ct++, (uword) (vdata - (char *) rec), (const ubyte *) rec); if (opdb_rec == NULL) { fatal(MYNAME ": libpdb couldn't create record\n"); @@ -408,6 +449,7 @@ data_write(void) ff_vecs_t gpilots_vecs = { ff_type_file, + FF_CAP_RW_WPT, rd_init, wr_init, rd_deinit, diff --git a/gpspilot.c b/gpspilot.c index 7863af855..712b0e392 100644 --- a/gpspilot.c +++ b/gpspilot.c @@ -122,7 +122,7 @@ data_read(void) waypoint *wpt_tmp; char *vdata; - wpt_tmp = xcalloc(sizeof(*wpt_tmp),1); + wpt_tmp = waypt_new(); rec = (struct record *) pdb_rec->data; wpt_tmp->longitude = be_read32(&rec->longitude) / 3.6e6; @@ -207,7 +207,7 @@ gpspilot_writewpt(const waypoint *wpt) } vdata += strlen( vdata ) + 1; - opdb_rec = new_Record (0, 2, ct++, vdata-(char *)rec, (const ubyte *)rec); + opdb_rec = new_Record (0, 2, ct++, (uword) (vdata-(char *)rec), (const ubyte *)rec); if (opdb_rec == NULL) { fatal(MYNAME ": libpdb couldn't create record\n"); @@ -247,6 +247,7 @@ data_write(void) ff_vecs_t gpspilot_vecs = { ff_type_file, + FF_CAP_RW_WPT, rd_init, wr_init, rd_deinit, diff --git a/gpsutil.c b/gpsutil.c index eeec5659f..ae648d093 100644 --- a/gpsutil.c +++ b/gpsutil.c @@ -84,7 +84,7 @@ data_read(void) sscanf(&ibuf[70], "%2c", icon); rtrim(desc); rtrim(icon); - wpt_tmp = xcalloc(sizeof(*wpt_tmp),1); + wpt_tmp = waypt_new(); wpt_tmp->altitude = alt; wpt_tmp->shortname = xstrdup(name); wpt_tmp->description = xstrdup(desc); @@ -118,7 +118,7 @@ gpsutil_disp(const waypoint *wpt) fprintf(file_out, "%-8s %08.3f%c %09.3f%c %07.0f%c %-30.30s %s\n", global_opts.synthesize_shortnames ? - mkshort(mkshort_handle, wpt->description) : + mkshort_from_wpt(mkshort_handle, wpt) : wpt->shortname, fabs(lat), lat < 0.0 ? 'S' : 'N', @@ -141,6 +141,7 @@ data_write(void) ff_vecs_t gpsutil_vecs = { ff_type_file, + FF_CAP_RW_WPT, rd_init, wr_init, rd_deinit, diff --git a/gpx.c b/gpx.c index 7b9830da3..73ef4596e 100644 --- a/gpx.c +++ b/gpx.c @@ -1,7 +1,7 @@ /* Access GPX data files. - Copyright (C) 2002, 2003, 2004 Robert Lipe, robertlipe@usa.net + Copyright (C) 2002, 2003, 2004, 2005 Robert Lipe, robertlipe@usa.net This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,6 +20,7 @@ */ #include "defs.h" +#include "xmlgeneric.h" #ifndef NO_EXPAT #include static XML_Parser psr; @@ -31,6 +32,8 @@ static char *opt_logpoint = NULL; static int logpoint_ct = 0; static const char *gpx_version; +static char *gpx_wversion; +static int gpx_wversion_num; static const char *gpx_creator; static char *xsi_schema_loc; @@ -49,7 +52,6 @@ static int input_string_len = 0; static time_t file_time; -static char *gsshortnames = NULL; static char *snlen = NULL; static char *suppresswhite = NULL; static char *urlbase = NULL; @@ -59,6 +61,17 @@ static route_head *rte_head; #define MYNAME "GPX" #define MY_CBUF 4096 #define DEFAULT_XSI_SCHEMA_LOC "http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd" +#define DEFAULT_XSI_SCHEMA_LOC_FMT "\"http://www.topografix.com/GPX/%c/%c http://www.topografix.com/GPX/%c/%c/gpx.xsd\"" + +/* + * Format used for floating point formats. Put in one place to make it + * easier to tweak when comparing output with other GPX programs that + * have more or less digits of output... + */ +/* #define FLT_FMT "%.9lf" */ /* ExpertGPS */ +#define FLT_FMT "%0.9lf" +#define FLT_FMT_T "%lf" +#define FLT_FMT_R "%lf" typedef enum { tt_unknown = 0, @@ -77,6 +90,8 @@ typedef enum { tt_wpt_time, tt_wpt_type, tt_wpt_urlname, + tt_wpt_link, /* New in GPX 1.1 */ + tt_wpt_link_text, /* New in GPX 1.1 */ tt_cache, tt_cache_name, tt_cache_container, @@ -87,6 +102,9 @@ typedef enum { tt_cache_desc_short, tt_cache_desc_long, tt_cache_log_wpt, + tt_cache_log_type, + tt_cache_log_date, + tt_cache_placer, tt_rte, tt_rte_name, tt_rte_desc, @@ -145,6 +163,8 @@ tag_mapping tag_path_map[] = { { tt_wpt_desc, 0, "/gpx/wpt/desc" }, { tt_wpt_url, 0, "/gpx/wpt/url" }, { tt_wpt_urlname, 0, "/gpx/wpt/urlname" }, + { tt_wpt_link, 0, "/gpx/wpt/link" }, /* GPX 1.1 */ + { tt_wpt_link_text, 0, "/gpx/wpt/link/text" }, /* GPX 1.1 */ { tt_wpt_sym, 0, "/gpx/wpt/sym" }, { tt_wpt_type, 1, "/gpx/wpt/type" }, { tt_cache, 1, "/gpx/wpt/groundspeak:cache" }, @@ -157,6 +177,9 @@ tag_mapping tag_path_map[] = { { tt_cache_desc_short, 1, "/gpx/wpt/groundspeak:cache/groundspeak:short_description" }, { tt_cache_desc_long, 1, "/gpx/wpt/groundspeak:cache/groundspeak:long_description" }, { tt_cache_log_wpt, 1, "/gpx/wpt/groundspeak:cache/groundspeak:logs/groundspeak:log/groundspeak:log_wpt" }, + { tt_cache_log_type, 1, "/gpx/wpt/groundspeak:cache/groundspeak:logs/groundspeak:log/groundspeak:type" }, + { tt_cache_log_date, 1, "/gpx/wpt/groundspeak:cache/groundspeak:logs/groundspeak:log/groundspeak:date" }, + { tt_cache_placer, 1, "/gpx/wpt/groundspeak:cache/groundspeak:owner" }, { tt_rte, 0, "/gpx/rte" }, { tt_rte_name, 0, "/gpx/rte/name" }, @@ -189,24 +212,6 @@ tag_mapping tag_path_map[] = { {0} }; - -static void -write_xml_entity(FILE *ofd, const char *indent, - const char *tag, const char *value) -{ - char *tmp_ent = xml_entitize(value); - fprintf(ofd, "%s<%s>%s\n", indent, tag, tmp_ent, tag); - xfree(tmp_ent); -} - -static void -write_optional_xml_entity(FILE *ofd, const char *indent, - const char *tag, const char *value) -{ - if (value && *value) - write_xml_entity(ofd, indent, tag, value); -} - static tag_type get_tag(const char *t, int *passthrough) { @@ -427,6 +432,11 @@ gpx_start(void *data, const char *el, const char **attr) case tt_wpt: tag_wpt(attr); break; + case tt_wpt_link: + if (0 == strcmp(attr[0], "href")) { + wpt_tmp->url = xstrdup(attr[1]); + } + break; case tt_rte: rte_head = route_head_alloc(); route_add_head(rte_head); @@ -468,12 +478,18 @@ gs_type_mapping{ geocache_type type; const char *name; } gs_type_map[] = { - { gt_traditional, "Traditional cache" }, - { gt_multi, "Multi-Cache" }, - { gt_virtual, "Virtual cache" }, - { gt_event, "Event cache" }, + { gt_traditional, "Traditional Cache" }, + { gt_multi, "Multi-cache" }, + { gt_virtual, "Virtual Cache" }, + { gt_event, "Event Cache" }, { gt_webcam, "Webcam Cache" }, - { gt_suprise, "Unknown cache" }, + { gt_suprise, "Unknown Cache" }, + { gt_earth, "Earthcache" }, + { gt_cito, "Cache In Trash Out Event" }, + { gt_letterbox, "Letterbox Hybrid" }, + { gt_locationless, "Locationless (Reverse) Cache" }, + + { gt_benchmark, "Benchmark" }, /* Not Groundspeak; for GSAK */ }; struct @@ -490,7 +506,7 @@ gs_container_mapping{ }; geocache_type -gs_mktype(char *t) +gs_mktype(const char *t) { int i; int sz = sizeof(gs_type_map) / sizeof(gs_type_map[0]); @@ -518,7 +534,7 @@ gs_get_cachetype(geocache_type t) } geocache_container -gs_mkcont(char *t) +gs_mkcont(const char *t) { int i; int sz = sizeof(gs_container_map) / sizeof(gs_container_map[0]); @@ -546,7 +562,7 @@ gs_get_container(geocache_container t) } time_t -xml_parse_time( char *cdatastr ) +xml_parse_time( const char *cdatastr ) { int off_hr = 0; int off_min = 0; @@ -613,6 +629,7 @@ gpx_end(void *data, const char *el) float x; char *cdatastrp = cdatastr.mem; int passthrough; + static time_t gc_log_date; if (strcmp(s + 1, el)) { fprintf(stderr, "Mismatched tag %s\n", el); @@ -643,6 +660,7 @@ gpx_end(void *data, const char *el) wpt_tmp->url = xstrdup(cdatastrp); break; case tt_wpt_urlname: + case tt_wpt_link_text: wpt_tmp->url_link_text = xstrdup(cdatastrp); break; case tt_wpt: @@ -652,11 +670,7 @@ gpx_end(void *data, const char *el) wpt_tmp = NULL; break; case tt_cache_name: - if (gsshortnames) { - if (wpt_tmp->notes) - xfree(wpt_tmp->notes); - wpt_tmp->notes = xstrdup(cdatastrp); - } + wpt_tmp->notes = xstrdup(cdatastrp); break; case tt_cache_container: wpt_tmp->gc_data.container = gs_mkcont(cdatastrp); @@ -692,6 +706,24 @@ gpx_end(void *data, const char *el) sscanf(cdatastrp, "%f", &x); wpt_tmp->gc_data.terr = x * 10; break; + case tt_cache_placer: + wpt_tmp->gc_data.placer = xstrdup(cdatastrp); + break; + case tt_cache_log_date: + gc_log_date = xml_parse_time( cdatastrp ); + break; + /* + * "Found it" logs follow the date according to the schema, + * if this is the first "found it" for this waypt, just use the + * last date we saw in this log. + */ + case tt_cache_log_type: + if ((0 == strcmp(cdatastrp, "Found it")) && + (0 == wpt_tmp->gc_data.last_found)) { + wpt_tmp->gc_data.last_found = gc_log_date; + } + gc_log_date = 0; + break; /* * Route-specific tags. */ @@ -744,7 +776,7 @@ gpx_end(void *data, const char *el) case tt_rte_rtept_sym: case tt_trk_trkseg_trkpt_sym: wpt_tmp->icon_descr = xstrdup(cdatastrp); - wpt_tmp->icon_descr_is_dynamic = 1; + wpt_tmp->wpt_flags.icon_descr_is_dynamic = 1; break; case tt_wpt_time: case tt_trk_trkseg_trkpt_time: @@ -998,31 +1030,6 @@ gpx_read(void) #endif /* NO_EXPAT */ } -/* - * - */ -static -void -gpx_write_time(const time_t timep, char *elname) -{ - struct tm *tm = gmtime(&timep); - - if (!tm) - return; - - fprintf(ofd, "<%s>%02d-%02d-%02dT%02d:%02d:%02dZ\n", - elname, - tm->tm_year+1900, - tm->tm_mon+1, - tm->tm_mday, - tm->tm_hour, - tm->tm_min, - tm->tm_sec, - elname - ); - -} - static void fprint_tag_and_attrs( char *prefix, char *suffix, xml_tag *tag ) { @@ -1059,7 +1066,7 @@ fprint_xml_chain( xml_tag *tag, const waypoint *wpt ) } if ( strcmp(tag->tagname, "groundspeak:cache" ) == 0 && wpt->gc_data.exported) { - gpx_write_time( wpt->gc_data.exported, + xml_write_time( ofd, wpt->gc_data.exported, "groundspeak:exported" ); } fprintf( ofd, "", tag->tagname); @@ -1106,10 +1113,36 @@ void free_gpx_extras( xml_tag *tag ) } } +/* + * Handle the grossness of GPX 1.0 vs. 1.1 handling of linky links. + */ static void -gpx_waypt_pr(const waypoint *waypointp) +write_gpx_url(const waypoint *waypointp) { char *tmp_ent; + + if (waypointp->url) { + tmp_ent = xml_entitize(waypointp->url); + if (gpx_wversion_num > 10) { + + fprintf(ofd, " \n", + urlbase ? urlbase : "", tmp_ent); + write_optional_xml_entity(ofd, " ", "text", + waypointp->url_link_text); + fprintf(ofd, " \n"); + } else { + fprintf(ofd, " %s%s\n", + urlbase ? urlbase : "", tmp_ent); + write_optional_xml_entity(ofd, " ", "urlname", + waypointp->url_link_text); + } + xfree(tmp_ent); + } +} + +static void +gpx_waypt_pr(const waypoint *waypointp) +{ const char *oname; char *odesc; @@ -1128,28 +1161,24 @@ gpx_waypt_pr(const waypoint *waypointp) mkshort(mkshort_handle, odesc) : waypointp->shortname; - fprintf(ofd, "\n", + fprintf(ofd, "\n", waypointp->latitude, waypointp->longitude); - if (waypointp->creation_time) { - gpx_write_time(waypointp->creation_time, "time"); - } if (waypointp->altitude != unknown_alt) { fprintf(ofd, " %f\n", waypointp->altitude); } + if (waypointp->creation_time) { + xml_write_time(ofd, waypointp->creation_time, "time"); + } write_optional_xml_entity(ofd, " ", "name", oname); write_optional_xml_entity(ofd, " ", "cmt", waypointp->description); if (waypointp->notes && waypointp->notes[0]) write_xml_entity(ofd, " ", "desc", waypointp->notes); else write_optional_xml_entity(ofd, " ", "desc", waypointp->description); - if (waypointp->url) { - tmp_ent = xml_entitize(waypointp->url); - fprintf(ofd, " %s%s\n", urlbase ? urlbase : "", tmp_ent); - xfree(tmp_ent); - } - write_optional_xml_entity(ofd, " ", "urlname", waypointp->url_link_text); + write_gpx_url(waypointp); + write_optional_xml_entity(ofd, " ", "sym", waypointp->icon_descr); fprint_xml_chain( waypointp->gpx_extras, waypointp ); @@ -1171,16 +1200,27 @@ gpx_track_hdr(const route_head *rte) static void gpx_track_disp(const waypoint *waypointp) { - fprintf(ofd, "\n", + fprintf(ofd, "\n", waypointp->latitude, waypointp->longitude); if (waypointp->altitude != unknown_alt) { - fprintf(ofd, "%f\n", + fprintf(ofd, " %f\n", waypointp->altitude); } if (waypointp->creation_time) { - gpx_write_time(waypointp->creation_time,"time"); + xml_write_time(ofd, waypointp->creation_time,"time"); + } + + /* GPX doesn't require a name on output, so if we made one up + * on input, we might as well say nothing. + */ + if (!waypointp->wpt_flags.shortname_is_synthetic) { + write_optional_xml_entity(ofd, " ", "name", + waypointp->shortname); } + write_optional_xml_entity(ofd, " ", "desc", waypointp->notes); + write_gpx_url(waypointp); + write_optional_xml_entity(ofd, " ", "sym", waypointp->icon_descr); fprintf(ofd, "\n"); } @@ -1211,7 +1251,7 @@ gpx_route_hdr(const route_head *rte) static void gpx_route_disp(const waypoint *waypointp) { - fprintf(ofd, " \n", + fprintf(ofd, " \n", waypointp->latitude, waypointp->longitude); @@ -1220,7 +1260,7 @@ gpx_route_disp(const waypoint *waypointp) waypointp->altitude); } if (waypointp->creation_time) { - gpx_write_time(waypointp->creation_time,"time"); + xml_write_time(ofd, waypointp->creation_time,"time"); } write_optional_xml_entity(ofd, " ", "name", waypointp->shortname); write_optional_xml_entity(ofd, " ", "cmt", waypointp->description); @@ -1248,6 +1288,12 @@ gpx_write(void) time_t now = 0; int short_length; bounds bounds; + + gpx_wversion_num = strtod(gpx_wversion, NULL) * 10; + + if (gpx_wversion_num <= 0) { + fatal(MYNAME ": gpx version number of '%s' not valid.\n", gpx_wversion); + } now = current_time(); @@ -1263,13 +1309,23 @@ gpx_write(void) setshort_length(mkshort_handle, short_length); fprintf(ofd, "\n"); - fprintf(ofd, "\n", xsi_schema_loc ? xsi_schema_loc : DEFAULT_XSI_SCHEMA_LOC); + fprintf(ofd, "xmlns=\"http://www.topografix.com/GPX/%c/%c\"\n", gpx_wversion[0], gpx_wversion[2]); + if (xsi_schema_loc) { + fprintf(ofd, "xsi:schemaLocation=\"%s\">\n", xsi_schema_loc); + } else { + fprintf(ofd, + "xsi:schemaLocation=" DEFAULT_XSI_SCHEMA_LOC_FMT">\n", + gpx_wversion[0], gpx_wversion[2], + gpx_wversion[0], gpx_wversion[2]); + } - gpx_write_time( now, "time" ); + if (gpx_wversion_num > 10) { + fprintf(ofd, "\n"); + } + xml_write_time( ofd, now, "time" ); waypt_compute_bounds(&bounds); if (bounds.max_lat > -360) { fprintf(ofd, " 10) { + fprintf(ofd, "\n"); + } + waypt_disp_all(gpx_waypt_pr); - gpx_track_pr(); gpx_route_pr(); + gpx_track_pr(); fprintf(ofd, "\n"); } static arglist_t gpx_args[] = { - { "gsshortnames", &gsshortnames, - "Prefer shorter descriptions from Groundspeak files", - NULL, ARGTYPE_BOOL }, { "snlen", &snlen, "Length of generated shortnames", NULL, ARGTYPE_INT }, { "suppresswhite", &suppresswhite, @@ -1299,11 +1357,14 @@ arglist_t gpx_args[] = { NULL, ARGTYPE_BOOL }, { "urlbase", &urlbase, "Base URL for link tag in output", NULL, ARGTYPE_STRING}, + { "gpxver", &gpx_wversion, "Target GPX version for output", + "1.0", ARGTYPE_STRING}, { 0, 0, 0, 0, 0 } }; ff_vecs_t gpx_vecs = { ff_type_file, + FF_CAP_RW_ALL, gpx_rd_init, gpx_wr_init, gpx_rd_deinit, diff --git a/gpxval b/gpxval index 2447c1d2f..98e694770 100644 --- a/gpxval +++ b/gpxval @@ -1,8 +1,32 @@ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/robertl/xerces-c1_7_0-linux7.2/lib export PATH=$PATH:/home/robertl/xerces-c1_7_0-linux7.2/bin +gpxval() +{ + echo "Validating $*" + ./gpsbabel $* -o gpx -F /tmp/$$.gpx + SAX2Count /tmp/$$.gpx + ./gpsbabel $* -o gpx,gpxver=1.0 -F /tmp/$$.gpx + SAX2Count /tmp/$$.gpx + ./gpsbabel $* -o gpx,gpxver=1.1 -F /tmp/$$.gpx + SAX2Count /tmp/$$.gpx +} + + +# gpxval "-i gpx -f reference/holux.gpx" +gpxval -i mapsend -f reference/chicago.trk + SAX2Count reference/holux.gpx -./gpsbabel -i gpx -f reference/holux.gpx -o gpx -F /tmp/1.gpx -SAX2Count /tmp/1.gpx -./gpsbabel -i mapsend -f reference/chicago.trk -o gpx -F /tmp/2.gpx -SAX2Count /tmp/2.gpx + +# Routes + +# gpxval -i gpx -f reference/route/blah.gpx +gpxval -i magellan -f reference/route/magellan.rte +gpxval -i psitrex -f reference/route/psitrtes.txt +# gpxval -i gpx -f reference/route/route.gpx +gpxval -i mapsend -f reference/route/route.mapsend +gpxval -i mapsource -f reference/route/route.mps + +# Tracks + +gpxval -i mapsource -f reference/route/route.mps diff --git a/hiketech.c b/hiketech.c new file mode 100644 index 000000000..a1d026485 --- /dev/null +++ b/hiketech.c @@ -0,0 +1,281 @@ +/* + Access Hiketech XML data files. + + Copyright (C) 2004,2005 Robert Lipe, robertlipe@usa.net + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + + */ + +#include "defs.h" +#include "xmlgeneric.h" + +static FILE *ofd; +static waypoint *wpt_tmp; +static route_head *trk_head; + + +#define MYNAME "hiketech" + +static +arglist_t hiketech_args[] = { + {0, 0, 0, 0, 0} +}; + +/* Waypoints */ +static xg_callback ht_wpt_s; +static xg_callback ht_wpt_e; +static xg_callback ht_ident; +static xg_callback ht_sym; +static xg_callback ht_lat; +static xg_callback ht_long; +static xg_callback ht_alt; + +/* Tracks */ +static xg_callback ht_trk_s, ht_trk_e; +static xg_callback ht_trk_ident; +static xg_callback ht_trk_pnt_s, ht_trk_pnt_e; +static xg_callback ht_trk_utc; +static xg_callback ht_trk_lat; +static xg_callback ht_trk_long; +static xg_callback ht_trk_alt; + +static xg_tag_mapping ht_map[] = { + { ht_wpt_s, cb_start, "/hiketech/gpsdata/wpt" }, + { ht_wpt_e, cb_end, "/hiketech/gpsdata/wpt" }, + { ht_ident, cb_cdata, "/hiketech/gpsdata/wpt/ident" }, + { ht_sym, cb_cdata, "/hiketech/gpsdata/wpt/sym" }, + { ht_lat, cb_cdata, "/hiketech/gpsdata/wpt/lat" }, + { ht_long, cb_cdata, "/hiketech/gpsdata/wpt/long" }, + { ht_alt, cb_cdata, "/hiketech/gpsdata/wpt/alt" }, + + { ht_trk_s, cb_start, "/hiketech/gpsdata/trk" }, + { ht_trk_e, cb_end, "/hiketech/gpsdata/trk" }, + { ht_trk_ident, cb_cdata, "/hiketech/gpsdata/trk/ident" }, + { ht_trk_pnt_s, cb_start, "/hiketech/gpsdata/trk/pnt" }, + { ht_trk_pnt_e, cb_end, "/hiketech/gpsdata/trk/pnt" }, + { ht_trk_utc, cb_cdata, "/hiketech/gpsdata/trk/pnt/utc" }, + { ht_trk_lat, cb_cdata, "/hiketech/gpsdata/trk/pnt/lat" }, + { ht_trk_long, cb_cdata, "/hiketech/gpsdata/trk/pnt/long" }, + { ht_trk_alt, cb_cdata, "/hiketech/gpsdata/trk/pnt/alt" }, + { NULL, 0, NULL} +}; + +void +hiketech_rd_init(const char *fname) +{ + xml_init(fname, ht_map); +} + +void +hiketech_read(void) +{ + xml_read(); +} + +void +hiketech_rd_deinit(void) +{ +} + +void +hiketech_wr_init(const char *fname) +{ + ofd = xfopen(fname, "w", MYNAME); +} + +void +hiketech_wr_deinit(void) +{ + fclose(ofd); +} + +static void +hiketech_trk_hdr(const route_head *rte) +{ + fprintf(ofd, "\n"); + write_optional_xml_entity(ofd, " ", "ident", rte->rte_name); +} + +static void +hiketech_trk_tlr(const route_head *rte) +{ + fprintf(ofd, "\n"); +} + +void +hiketech_print_utc(time_t tm, const char *indent, const char *tag) +{ + char tbuf[80]; + strftime(tbuf, sizeof(tbuf), "%Y-%m-%d %I:%M:%S", gmtime(&tm)); + fprintf(ofd, "%s<%s>%s\n",indent,tag,tbuf,tag); +} + +static void +hiketech_trkpt_pr(const waypoint *waypointp) +{ + fprintf(ofd, " \n"); + if (waypointp->creation_time) { + hiketech_print_utc(waypointp->creation_time, " ", "utc"); + } + fprintf(ofd, " %f\n", waypointp->latitude); + fprintf(ofd, " %f\n", waypointp->longitude); + if (waypointp->altitude != unknown_alt) { + fprintf(ofd, " %f\n", + waypointp->altitude); + } + fprintf(ofd, " \n"); +} + +static void +hiketech_waypt_pr(const waypoint *wpt) +{ + fprintf(ofd, "\n"); + write_xml_entity(ofd, "\t", "ident", wpt->shortname); + write_optional_xml_entity(ofd, "\t", "sym", wpt->icon_descr); + fprintf(ofd, "\t%f\n", wpt->latitude); + fprintf(ofd, "\t%f\n", wpt->longitude); + + /* + * These probably aren't technicallyconstants, but it's all + * we can do for now. + */ + fprintf(ofd, "\t\n\t\tFAFFB4\n\t\tFF8000\n\t\n"); + fprintf(ofd, "\n"); +} + +void +hiketech_write(void) +{ + fprintf(ofd, "\n"); + fprintf(ofd, "\n"); + track_disp_all(hiketech_trk_hdr, hiketech_trk_tlr, hiketech_trkpt_pr); + track_disp_all(NULL, NULL, hiketech_trkpt_pr); + waypt_disp_all(hiketech_waypt_pr); + fprintf(ofd, "\n"); + fprintf(ofd, "\n"); +} + +void ht_wpt_s(const char *args, const char **unused) +{ + wpt_tmp = waypt_new(); +} + +void ht_ident(const char *args, const char **unused) +{ + wpt_tmp->shortname = xstrdup(args); +} + +void ht_sym(const char *args, const char **unused) +{ + wpt_tmp->icon_descr = xstrdup(args); + wpt_tmp->wpt_flags.icon_descr_is_dynamic = 1; +} + +void ht_lat(const char *args, const char **unused) +{ + wpt_tmp->latitude = atof(args); +} + +void ht_long(const char *args, const char **unused) +{ + wpt_tmp->longitude = atof(args); +} + +void ht_alt(const char *args, const char **unused) +{ + wpt_tmp->altitude = atof(args); +} + +void ht_wpt_e(const char *args, const char **unused) +{ + waypt_add(wpt_tmp); + wpt_tmp = NULL; +} + +void ht_trk_s(const char *args, const char **unused) +{ + trk_head = route_head_alloc(); + track_add_head(trk_head); +} + +void ht_trk_e(const char *args, const char **unused) +{ + +} + +void ht_trk_ident(const char *args, const char **unused) +{ + trk_head->rte_name = xstrdup(args); +} + +void ht_trk_pnt_s(const char *args, const char **unused) +{ + wpt_tmp = waypt_new(); +} + +void ht_trk_pnt_e(const char *args, const char **unused) +{ + route_add_wpt(trk_head, wpt_tmp); +} + +void ht_trk_utc(const char *args, const char **unused) +{ + struct tm tm; + time_t utc; + + sscanf(args, "%d-%d-%d %d:%d:%d", + &tm.tm_year, &tm.tm_mon, + &tm.tm_mday, &tm.tm_hour, + &tm.tm_min, &tm.tm_sec); + tm.tm_mon -= 1; + tm.tm_year -= 1900; + tm.tm_isdst = 0; + + utc = mktime(&tm) + get_tz_offset() ; + + wpt_tmp->creation_time = utc; +} + +void ht_trk_lat(const char *args, const char **unused) +{ + wpt_tmp->latitude = atof(args); +} + +void ht_trk_long(const char *args, const char **unused) +{ + wpt_tmp->longitude = atof(args); +} + +void ht_trk_alt(const char *args, const char **unused) +{ + wpt_tmp->altitude = atof(args); +} + + + +ff_vecs_t hiketech_vecs = { + ff_type_file, + { ff_cap_read | ff_cap_write, ff_cap_read | ff_cap_write }, + hiketech_rd_init, + hiketech_wr_init, + hiketech_rd_deinit, + hiketech_wr_deinit, + hiketech_read, + hiketech_write, + NULL, + hiketech_args +}; + diff --git a/holux.c b/holux.c index 41735b2d4..03613ff7f 100644 --- a/holux.c +++ b/holux.c @@ -106,7 +106,7 @@ static void data_read(void) /* Get the waypoints */ for (iCount = 0; iCount < iWptNum ; iCount ++) { - wpt_tmp = xcalloc(sizeof(*wpt_tmp), 1); + wpt_tmp = waypt_new(); iWptIndex = le_read16(&((WPTHDR *)HxWpt)->idx[iCount]); pWptHxTmp = (WPT *)&HxWpt[OFFS_WPT + (sizeof(WPT) * iWptIndex)]; @@ -291,6 +291,7 @@ static void data_write(void) ff_vecs_t holux_vecs = { ff_type_file, + FF_CAP_RW_WPT, rd_init, wr_init, rd_deinit, diff --git a/hsa_ndv.c b/hsa_ndv.c index 7cfa2c66d..d52452048 100644 --- a/hsa_ndv.c +++ b/hsa_ndv.c @@ -309,9 +309,8 @@ hsa_ndv_waypt_pr(const waypoint *waypointp) // fprintf(ofd, "\t\t\t0\n"); // fprintf(ofd, "\t\t\t1\n"); // fprintf(ofd, "\t\t\t1089009023\n"); - fprintf(ofd, "\t\t\tattr=grpnam%s\x1ftrnrad50\x1fOBJNAM%s\x1flegnum%i\x1fusrmrk%s\x1fselect2\n", - routeName, waypointp->shortname, legNum, waypointp->description); - fprintf(ofd, "\t\t\tattr=grpnam%s\x1f\n", routeName); + fprintf(ofd, "\t\t\t\n", routeName, waypointp->shortname, legNum, waypointp->description); + fprintf(ofd, "\t\t\t\n", routeName); fprintf(ofd, "\t\t\t1\n"); fprintf(ofd, "\t\t\t%lf\n", waypointp->latitude); fprintf(ofd, "\t\t\t%lf\n", waypointp->longitude); @@ -345,6 +344,7 @@ hsa_ndv_write(void) ff_vecs_t HsaEndeavourNavigator_vecs = { ff_type_file, + FF_CAP_RW_WPT, hsa_ndv_rd_init, hsa_ndv_wr_init, hsa_ndv_rd_deinit, diff --git a/html.c b/html.c index bc00b547e..ab72d1c49 100644 --- a/html.c +++ b/html.c @@ -66,12 +66,12 @@ html_disp(const waypoint *wpt) int latint, lonint; char tbuf[1024]; time_t tm = wpt->creation_time; - long utmz; + int32 utmz; double utme, utmn; char utmzc; - lonint = abs(wpt->longitude); - latint = abs(wpt->latitude); + lonint = abs((int) wpt->longitude); + latint = abs((int) wpt->latitude); GPS_Math_WGS84_To_UTM_EN(wpt->latitude, wpt->longitude, &utme, &utmn, &utmz, &utmzc); @@ -83,7 +83,7 @@ html_disp(const waypoint *wpt) fprintf(file_out, "
\n"); fprintf(file_out, "
\n", wpt->shortname); fprintf(file_out, "

%s - %c%d°%06.3f %c%d°%06.3f (%ld%c %6.0f %7.0f)", - (global_opts.synthesize_shortnames) ? mkshort(mkshort_handle, wpt->description) : wpt->shortname, + (global_opts.synthesize_shortnames) ? mkshort_from_wpt(mkshort_handle, wpt) : wpt->shortname, wpt->latitude < 0 ? 'S' : 'N', latint, 60.0 * (fabs(wpt->latitude) - latint), wpt->longitude < 0 ? 'W' : 'E', lonint, 60.0 * (fabs(wpt->longitude) - lonint), utmz, utmzc, utme, utmn); @@ -104,10 +104,14 @@ html_disp(const waypoint *wpt) } if (wpt->gc_data.terr) { if (wpt->gc_data.desc_short.utfstring) { - fprintf (file_out, "

%s

\n", strip_nastyhtml(wpt->gc_data.desc_short.utfstring)); + char *tmpstr = strip_nastyhtml(wpt->gc_data.desc_short.utfstring); + fprintf (file_out, "

%s

\n", tmpstr ); + xfree( tmpstr ); } if (wpt->gc_data.desc_long.utfstring) { - fprintf (file_out, "

%s

\n", strip_nastyhtml(wpt->gc_data.desc_long.utfstring)); + char *tmpstr = strip_nastyhtml(wpt->gc_data.desc_long.utfstring); + fprintf (file_out, "

%s

\n", tmpstr ); + xfree( tmpstr ); } if (wpt->gc_data.hint) { char *hint = NULL; @@ -254,6 +258,7 @@ data_write(void) ff_vecs_t html_vecs = { ff_type_file, + { ff_cap_write, ff_cap_none, ff_cap_none }, NULL, wr_init, NULL, diff --git a/igc.c b/igc.c index 5ccbfb0c6..188e7d378 100644 --- a/igc.c +++ b/igc.c @@ -518,8 +518,8 @@ static char *latlon2str(const waypoint * wpt) char lon_hemi = wpt->longitude < 0 ? 'W' : 'E'; unsigned char lat_deg = fabs(wpt->latitude); unsigned char lon_deg = fabs(wpt->longitude); - unsigned int lat_min = (fabs(wpt->latitude) - lat_deg) * 60000 + 0.5; - unsigned int lon_min = (fabs(wpt->longitude) - lon_deg) * 60000 + 0.5; + unsigned int lat_min = (fabs(wpt->latitude) - lat_deg) * 60000 + 0.500000000001; + unsigned int lon_min = (fabs(wpt->longitude) - lon_deg) * 60000 + 0.500000000001; if (snprintf(str, 18, "%02u%05u%c%03u%05u%c", lat_deg, lat_min, lat_hemi, lon_deg, lon_min, lon_hemi) != 17) { @@ -842,20 +842,20 @@ static void wr_track(void) QUEUE_FOR_EACH(&gnss_track->waypoint_list, elem, tmp) { wpt = (waypoint *) elem; pres_alt = interpolate_alt(pres_track, wpt->creation_time + time_adj); - wr_fix_record(wpt, pres_alt, wpt->altitude); + wr_fix_record(wpt, (int) pres_alt, (int) wpt->altitude); } } else { if (pres_track) { // Only the pressure altitude track was found so generate fix // records from it alone. QUEUE_FOR_EACH(&pres_track->waypoint_list, elem, tmp) { - wr_fix_record((waypoint *) elem, ((waypoint *) elem)->altitude, unknown_alt); + wr_fix_record((waypoint *) elem, (int) ((waypoint *) elem)->altitude, (int) unknown_alt); } } else if (gnss_track) { // Only the GNSS altitude track was found so generate fix // records from it alone. QUEUE_FOR_EACH(&gnss_track->waypoint_list, elem, tmp) { - wr_fix_record((waypoint *) elem, unknown_alt, ((waypoint *) elem)->altitude); + wr_fix_record((waypoint *) elem, (int) unknown_alt, (int) ((waypoint *) elem)->altitude); } } else { // No tracks found so nothing to do @@ -894,6 +894,7 @@ static arglist_t igc_args[] = { ff_vecs_t igc_vecs = { ff_type_file, + { ff_cap_none , ff_cap_read | ff_cap_write, ff_cap_read | ff_cap_write }, rd_init, wr_init, rd_deinit, diff --git a/intdoc/GPSBabel Windows GUI 2.00.00 Project Plan.pdf b/intdoc/GPSBabel Windows GUI 2.00.00 Project Plan.pdf new file mode 100644 index 0000000000000000000000000000000000000000..2dc786566372ae79af9dc35ff3c8f1ac87732762 GIT binary patch literal 68640 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 U+&^zxP=p&ovFPbVWyP@mAFusXegFUf literal 0 HcmV?d00001 diff --git a/intdoc/SA2003_an1_dump.pl b/intdoc/SA2003_an1_dump.pl new file mode 100644 index 000000000..5bbb690d1 --- /dev/null +++ b/intdoc/SA2003_an1_dump.pl @@ -0,0 +1,200 @@ +#!/usr/bin/perl + +=pod + + This script reads a DeLorme Street Atlas 2003 .an1 (drawing) file + and prints various pertinent data from it. Anything with a variable + name starting with "unk" or "magic" or "zero" is probably something + we don't yet understand. Suggestions as to what some of these fields + mean are welcome. The author disclaims any liability arising from + the use of any information contained within this script. + + Copyright (C) 2005 Ronald L. Parker (babelan1perl@parkrrrr.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + +=cut + +# Convert a longword to a latitude or longitude +sub decode { + my $foo = shift; + + my $deg = (0x80000000-$foo)/(0x800000); + sprintf( "%d %06.3f", $deg, 60*($deg-int($deg))); +} + + +# read a data structure from the input file. +sub shiftunpack { + + my $pattern = shift; + my @result = unpack( $pattern, $file ); + my $str = pack( $pattern, @result ); + $file = substr( $file, length( $str )); + @result; +} + +sub skip_bytes { + my $count = shift; + $file = substr( $file, $count ); +} + +sub decodeGuid { + ($a, $b, $c, $d, $e, $f, $g, $h, $i, $j) = unpack( 'LSSSCCCCCC', shift ); + sprintf( '%8.8x-%4.4x-%4.4x-%4.4x-%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x',$a, $b, $c, $d, $e, $f, $g, $h, $i, $j); +} + +# read file +undef $/; +$file = <>; + +@filetypes = qw( drawing road trail waypoint track ); + +# read file header +($magic, $filetype ) = shiftunpack( 'ss' ); + +print <bitmap$filecount.bmp"; + binmode BMP; + print BMP 'BM'; + $head = pack('lssl', ($fhsize, $res_0_1, $res_0_2, $bitoffset)); + print BMP $head; + $head = pack('lllssllllll', ($bmisize, $width, $height, $planes, $bpp, + $compression, $size, $xppm, $yppm, $colused, $colimprt)); + print BMP $head; + print BMP substr($file, 0, $palettesize+$size); + close BMP; + $filecount++; + + skip_bytes( $palettesize ); + # image + skip_bytes( $size ); + } + else { + # image information - the 'type' we read was actually the low word of the hotspot X coord. + ($hotspotxhi, $hotspoty, $unk1, $guid, $name ) = shiftunpack( 'slla[16]C/a*' ); + + # fix the hotspot X coord + $hotspotx = $rec_type + 0x10000*$hotspotxhi; + + printf( "Image: %2d %2d %s $name\n", $hotspotx, $hotspoty, decodeGuid( $guid ) ); + $imagenames{$guid} = $name; + $bitmapcount--; + } +} + +# waypoint information + +($magic, $wptcount) = shiftunpack( 'sl' ); + +@types = qw(none marker line polygon text circle mapnote highlight unknown8 arc spline rectangle + unknown12 unknown13 road trail track waypoint); + +print( "$wptcount waypoints\n" ); +while ( $wptcount ) { + + ($magic, $unk1, $lon, $lat, $type, $height, $width, $unk2, $unk3, $serial, + $unk4, $create_zoom, $visible_zoom, $unk5, $circle_radius, $name, $font, + $guid, $fontcolor, $fontstyle, $fontsize, $unk6, $outlinecolor, $unk7, + $fillcolor, $unk8, $unk9 ) = + shiftunpack( 'slllsllssssCCsds/a*s/a*a[16]lllllllll' ); + + # fontcolor is BGR (i.e. pure blue is 0xff00000, pure red is 0x0000ff) + # fontstyle is 0x10-bold, 0x20-italic, 0x80-underline + + # width/height are in pixels for mapnotes and represent the offset of the mapnote + # from the point (i.e. the dimensions of the tail.) + # width/height are in degrees times 0x800000 for rectangles + + # Note that type appears to be shared with lines. + # type desc + # 1 marker (flag, dot, etc.) + # 4 text + # 5 circle + # 6 mapnote + # 11 rectangle + # 17 waypoint + + $lat = decode( $lat ); + $lon = decode( $lon ); + + $rect_height = $height/0x800000; + $rect_width = $width/0x800000; + + printf ( "$magic -- %x %x %x %x %x %x %x %x %x -- $type $types[$type] $lat $lon %s $imagenames{$guid} '$name'\n", + $unk1, $unk2, $unk3, $unk4, $unk5, $unk6, $unk7, $unk8, $unk9, decodeGuid( $guid ) ); + + $wptcount--; +} + +# line information +($magic, $linecount ) = shiftunpack( 'sl' ); +print ( "$linecount lines\n" ); +while ( $linecount ) { + ($magic, $unk1, $serial, $unk2, $unk3, $type, $unk4, $name, $lineweight, $linestyle, + $linecolor, $unk5, $polyfillcolor, $unk6, $unk7, $unk8, $pointcount ) = + shiftunpack( 'ssslssls/a*sllllllsl' ); + + # arcs are 4-point (3-segment) lines: start, third point, end, center (yes, that's overdetermined.) + + # Note that type appears to be shared with points. + # type desc + # 2 line + # 3 polygon + # 7 highlight + # 9 arc + # 10 spline + # 14 routable road + # 15 trail + # 16 track + + printf ("--- start line --- %.4x %x %x %x %x %x %x %x %x -- $type $types[$type] '$name'\n", $magic, + $unk1, $unk2, $unk3, $unk4, $unk5, $unk6, $unk7, $unk8 ); + while ( $pointcount ) { + ($magic, $unk0, $lon, $lat, $unk0s ) = shiftunpack( 'sllls' ); + $lat = decode( $lat ); + $lon = decode( $lon ); + printf (" $magic $lat $lon %x %x\n", $unk0, $unk0s); + $pointcount--; + } + print "--- end line ---\n"; + $linecount--; +} + diff --git a/internal_styles.c b/internal_styles.c index 3b31cde74..49efddea3 100644 --- a/internal_styles.c +++ b/internal_styles.c @@ -27,7 +27,7 @@ static char arc[] = static char csv[] = "# gpsbabel XCSV style file\n" "#\n" -"# Format: Delorme SA 9.0 CSV\n" +"# Format: DeLorme SA 9.0 CSV\n" "# Author: Alex Mottram\n" "# Date: 12/09/2002\n" "#\n" @@ -45,9 +45,13 @@ static char csv[] = "#\n" "# INDIVIDUAL DATA FIELDS, IN ORDER OF APPEARANCE:\n" "#\n" -"IFIELD LAT_DECIMAL, \"\", \"%08.5f\"\n" -"IFIELD LON_DECIMAL, \"\", \"%08.5f\"\n" +"IFIELD LAT_HUMAN_READABLE, \"\", \"%08.5f\"\n" +"IFIELD LON_HUMAN_READABLE, \"\", \"%08.5f\"\n" "IFIELD DESCRIPTION, \"\", \"%s\"\n" + +"OFIELD LAT_DECIMAL, \"\", \"%08.5f\"\n" +"OFIELD LON_DECIMAL, \"\", \"%08.5f\"\n" +"OFIELD DESCRIPTION, \"\", \"%s\"\n" ; static char custom[] = "# gpsbabel XCSV style file\n" @@ -384,16 +388,16 @@ static char s_and_t[] = "# GC171C,44.70605,-85.62265,The Michigan Frog by RealDcoy & LRB,http://www.geocaching.com/seek/cache_details.aspx?ID=5916,Traditional Cache\n" "#\n" -"DESCRIPTION Microsoft Streets and Trips 2002/2003\n" +"DESCRIPTION Microsoft Streets and Trips 2002-2005\n" "#\n" "# FILE LAYOUT DEFINITIIONS:\n" "#\n" -"FIELD_DELIMITER COMMA\n" +"FIELD_DELIMITER TAB\n" "RECORD_DELIMITER NEWLINE\n" "BADCHARS ,\"\n" -"PROLOGUE Name,Latitude,Longitude,Name 2,URL,Type\n" +"PROLOGUE Name Latitude Longitude Description URL Type Container Diff Terr\n" "#\n" "# INDIVIDUAL DATA FIELDS, IN ORDER OF APPEARANCE:\n" @@ -405,7 +409,10 @@ static char s_and_t[] = "IFIELD LON_DECIMAL, \"\", \"%f\" # Longitude\n" "IFIELD DESCRIPTION, \"\", \"%s\" # Name 2 (Big Description)\n" "IFIELD URL, \"\", \"%s\" # URL\n" -"IFIELD IGNORE, \"\", \"\" # Holder for Geocache Type\n" +"IFIELD GEOCACHE_TYPE, \"\", \"%s\" # Geocache Type\n" +"IFIELD GEOCACHE_CONTAINER, \"\", \"%s\" # Geocache Type\n" +"IFIELD GEOCACHE_DIFF, \"\", \"%3.1f\" # Geocache Type\n" +"IFIELD GEOCACHE_TERR, \"\", \"%3.1f\" # Geocache Type\n" ; static char saplus[] = "# gpsbabel XCSV style file\n" @@ -415,7 +422,7 @@ static char saplus[] = "# Date: 02/22/04\n" "#\n" -"DESCRIPTION Delorme Street Atlas Plus\n" +"DESCRIPTION DeLorme Street Atlas Plus\n" "#\n" "# FILE LAYOUT DEFINITIIONS:\n" @@ -491,11 +498,13 @@ static char tabsep[] = "IFIELD GEOCACHE_TYPE,\"\",\"%s\"\n" "IFIELD PATH_DISTANCE_MILES,\"\",\"%f\"\n" "IFIELD PATH_DISTANCE_KM, \"\", \"%f\"\n" +"IFIELD GEOCACHE_PLACER,\"\",\"%s\"\n" +"IFIELD YYYYMMDD_TIME,\"\",\"%ld\"\n" ; static char xmap[] = "# gpsbabel XCSV style file\n" "#\n" -"# Format: Delorme Xmap Conduit\n" +"# Format: DeLorme Xmap Conduit\n" "# Author: Alex Mottram\n" "# Date: 12/09/2002\n" "#\n" @@ -503,7 +512,7 @@ static char xmap[] = "# As defined in csv.c/xmap\n" "#\n" -"DESCRIPTION Delorme XMap HH Native .WPT\n" +"DESCRIPTION DeLorme XMap HH Native .WPT\n" "EXTENSION wpt\n" "#\n" @@ -518,19 +527,23 @@ static char xmap[] = "#\n" "# INDIVIDUAL DATA FIELDS, IN ORDER OF APPEARANCE:\n" "#\n" -"IFIELD LAT_DECIMAL, \"\", \"%08.5f\"\n" -"IFIELD LON_DECIMAL, \"\", \"%08.5f\"\n" +"IFIELD LAT_HUMAN_READABLE, \"\", \"%08.5f\"\n" +"IFIELD LON_HUMAN_READABLE, \"\", \"%08.5f\"\n" "IFIELD DESCRIPTION, \"\", \"%s\"\n" + +"OFIELD LAT_DECIMAL, \"\", \"%08.5f\"\n" +"OFIELD LON_DECIMAL, \"\", \"%08.5f\"\n" +"OFIELD DESCRIPTION, \"\", \"%s\"\n" ; static char xmapwpt[] = "# gpsbabel XCSV style file\n" "#\n" -"# Format: Delorme Xmap HH Street Atlas USA .WPT (PocketPC)\n" +"# Format: DeLorme Xmap HH Street Atlas USA .WPT (PocketPC)\n" "# Author: Alex Mottram\n" "# Date: 12/09/2002\n" "#\n" "# \n" -"DESCRIPTION Delorme XMat HH Street Atlas USA .WPT (PPC)\n" +"DESCRIPTION DeLorme XMat HH Street Atlas USA .WPT (PPC)\n" "SHORTLEN 32\n" "SHORTWHITE 0\n" diff --git a/jeeps/gps.h b/jeeps/gps.h index 2c6f0c196..69dba75aa 100644 --- a/jeeps/gps.h +++ b/jeeps/gps.h @@ -149,6 +149,9 @@ typedef struct GPS_SWay int32 rte_link_class; char rte_link_subclass[18]; char rte_link_ident[256]; + + char Time_populated; /* 1 if true */ + time_t Time; /* Unix time */ } GPS_OWay, *GPS_PWay; @@ -179,7 +182,6 @@ extern double gps_save_version; extern char gps_save_string[GPS_ARB_LEN]; extern int gps_is_usb; - extern struct COMMANDDATA COMMAND_ID[2]; extern struct LINKDATA LINK_ID[3]; extern struct GPS_MODEL_PROTOCOL GPS_MP[]; @@ -190,7 +192,6 @@ extern char *gps_aviation_sym[]; extern char *gps_16_sym[]; - #endif #ifdef __cplusplus diff --git a/jeeps/gpsapp.c b/jeeps/gpsapp.c index 2db5a4df8..464845753 100644 --- a/jeeps/gpsapp.c +++ b/jeeps/gpsapp.c @@ -26,6 +26,7 @@ #include #include #include +#include #define XMIN(a,b) (a < b? a : b) @@ -48,7 +49,7 @@ static void GPS_D105_Get(GPS_PWay *way, UC *s); static void GPS_D106_Get(GPS_PWay *way, UC *s); static void GPS_D107_Get(GPS_PWay *way, UC *s); static void GPS_D108_Get(GPS_PWay *way, UC *s); -static void GPS_D109_Get(GPS_PWay *way, UC *s); +static void GPS_D109_Get(GPS_PWay *way, UC *s, int proto); static void GPS_D150_Get(GPS_PWay *way, UC *s); static void GPS_D151_Get(GPS_PWay *way, UC *s); static void GPS_D152_Get(GPS_PWay *way, UC *s); @@ -64,7 +65,7 @@ static void GPS_D105_Send(UC *data, GPS_PWay way, int32 *len); static void GPS_D106_Send(UC *data, GPS_PWay way, int32 *len); static void GPS_D107_Send(UC *data, GPS_PWay way, int32 *len); static void GPS_D108_Send(UC *data, GPS_PWay way, int32 *len); -static void GPS_D109_Send(UC *data, GPS_PWay way, int32 *len); +static void GPS_D109_Send(UC *data, GPS_PWay way, int32 *len, int proto); static void GPS_D150_Send(UC *data, GPS_PWay way, int32 *len); static void GPS_D151_Send(UC *data, GPS_PWay way, int32 *len); static void GPS_D152_Send(UC *data, GPS_PWay way, int32 *len); @@ -102,6 +103,30 @@ int gps_is_usb; double gps_save_version; char gps_save_string[GPS_ARB_LEN]; +/* + * Internal function to copy what Garmin describes as a "Character Array". + * Dest buffer is padded with spaces and must not contain nulls. Optionally + * we uppercase the string because some models (III's and 12's) react + * violently to lower case data. + */ +typedef enum { UpperNo = 0, UpperYes = 1 } copycase; +static +void copy_char_array(UC **dst, UC* src, int count, copycase mustupper) +{ + UC *d = *dst; + int ocount = count; + do { + UC sc = *src++; + if (sc == 0) { + while (count--) + *d++ = ' '; + break; + } + else *d++ = mustupper == UpperYes ? toupper(sc) : sc; + } while (--count) ; + *dst += ocount; +} + /* @func GPS_Init ****************************************************** ** @@ -319,10 +344,9 @@ static void GPS_A001(GPS_PPacket packet) } else if(data<200) { - if(data!=100) - GPS_Protocol_Error(tag,data); - else + if(data==100) gps_waypt_transfer = pA100; + /* Ignore A101 Waypoint Category Transfer Protocol. */ continue; } else if(data<300) @@ -415,7 +439,7 @@ static void GPS_A001(GPS_PPacket packet) { if(lasta<200) { - if(data<=109 && data>=100) + if(data<=110 && data>=100) { gps_waypt_type = data; continue; @@ -430,6 +454,11 @@ static void GPS_A001(GPS_PPacket packet) gps_waypt_type = data; continue; } + if (data == 120) + { + /* Quest 3.0 has a D120 for Wpt category ignore it*/ + continue; + } else GPS_Protocol_Error(tag,data); } @@ -448,7 +477,7 @@ static void GPS_A001(GPS_PPacket packet) continue; } - if(data<=109 && data>=100) + if(data<=110 && data>=100) { gps_rte_type = data; continue; @@ -588,7 +617,7 @@ static void GPS_A001(GPS_PPacket packet) ** ** @return [int32] number of waypoint entries ************************************************************************/ -int32 GPS_A100_Get(const char *port, GPS_PWay **way, int (*cb)()) +int32 GPS_A100_Get(const char *port, GPS_PWay **way, int (*cb)(int, GPS_PWay *)) { static UC data[2]; int32 fd; @@ -672,7 +701,10 @@ int32 GPS_A100_Get(const char *port, GPS_PWay **way, int (*cb)()) GPS_D108_Get(&((*way)[i]),rec->data); break; case pD109: - GPS_D109_Get(&((*way)[i]),rec->data); + GPS_D109_Get(&((*way)[i]),rec->data, 109); + break; + case pD110: + GPS_D109_Get(&((*way)[i]),rec->data, 110); break; case pD150: GPS_D150_Get(&((*way)[i]),rec->data); @@ -739,7 +771,7 @@ int32 GPS_A100_Get(const char *port, GPS_PWay **way, int (*cb)()) ** ** @return [int32] success ************************************************************************/ -int32 GPS_A100_Send(const char *port, GPS_PWay *way, int32 n, int (*cb)()) +int32 GPS_A100_Send(const char *port, GPS_PWay *way, int32 n, int (*cb)(GPS_PWay *)) { UC data[GPS_ARB_LEN]; int32 fd; @@ -754,7 +786,7 @@ int32 GPS_A100_Send(const char *port, GPS_PWay *way, int32 n, int (*cb)()) if(!(tra = GPS_Packet_New()) || !(rec = GPS_Packet_New())) return MEMORY_ERROR; - GPS_Util_Put_Short(data,n); + GPS_Util_Put_Short(data, (short) n); GPS_Make_Packet(&tra, LINK_ID[gps_link_type].Pid_Records, data,2); if(!GPS_Write_Packet(fd,tra)) @@ -769,7 +801,7 @@ int32 GPS_A100_Send(const char *port, GPS_PWay *way, int32 n, int (*cb)()) for(i=0;ialt = GPS_Util_Get_Float(p); p+=sizeof(float); - (*way)->dpth = (int32)GPS_Util_Get_Float(p); + (*way)->dpth = GPS_Util_Get_Float(p); p+=sizeof(float); - (*way)->dst = (int32)GPS_Util_Get_Float(p); + (*way)->dst = GPS_Util_Get_Float(p); p+=sizeof(float); for(i=0;i<2;++i) (*way)->state[i] = *p++; @@ -1245,8 +1280,11 @@ static void GPS_D108_Get(GPS_PWay *way, UC *s) ** @param [r] s [UC *] packet data ** ** @return [void] +** Quest uses D110's which are just like D109's but with the addition +** of temp, time, and wpt_cat stuck between ete and ident. Rather than +** duplicating the function, we just handle this at runtime. ************************************************************************/ -static void GPS_D109_Get(GPS_PWay *way, UC *s) +static void GPS_D109_Get(GPS_PWay *way, UC *s, int protoid) { UC *p; UC *q; @@ -1272,15 +1310,20 @@ static void GPS_D109_Get(GPS_PWay *way, UC *s) (*way)->alt = GPS_Util_Get_Float(p); p+=sizeof(float); - (*way)->dpth = (int32)GPS_Util_Get_Float(p); + (*way)->dpth = GPS_Util_Get_Float(p); p+=sizeof(float); - (*way)->dst = (int32)GPS_Util_Get_Float(p); + (*way)->dst = GPS_Util_Get_Float(p); p+=sizeof(float); for(i=0;i<2;++i) (*way)->state[i] = *p++; for(i=0;i<2;++i) (*way)->cc[i] = *p++; p += 4; /* Skip over "outbound link ete in seconds */ + if (protoid == 110) { + p += 4; /* skip float temp */ + p += 4; /* skip longword time */ + p += 2; /* skip int "category membership " */ + } q = (UC *) (*way)->ident; while((*q++ = *p++)); @@ -1562,18 +1605,17 @@ static void GPS_D155_Get(GPS_PWay *way, UC *s) static void GPS_D100_Send(UC *data, GPS_PWay way, int32 *len) { UC *p; - int32 i; p = data; - for(i=0;i<6;++i) *p++ = way->ident[i]; + copy_char_array(&p, way->ident, 6, UpperYes); GPS_Util_Put_Int(p,(int32)GPS_Math_Deg_To_Semi(way->lat)); p+=sizeof(int32); GPS_Util_Put_Int(p,(int32)GPS_Math_Deg_To_Semi(way->lon)); p+=sizeof(int32); GPS_Util_Put_Uint(p,0); p+=sizeof(int32); - for(i=0;i<40;++i) *p++ = way->cmnt[i]; + copy_char_array(&p, way->cmnt, 40, UpperYes); *len = 58; @@ -1594,18 +1636,18 @@ static void GPS_D100_Send(UC *data, GPS_PWay way, int32 *len) static void GPS_D101_Send(UC *data, GPS_PWay way, int32 *len) { UC *p; - int32 i; p = data; - for(i=0;i<6;++i) *p++ = way->ident[i]; + copy_char_array(&p, way->ident, 6, UpperYes); GPS_Util_Put_Int(p,(int32)GPS_Math_Deg_To_Semi(way->lat)); p+=sizeof(int32); GPS_Util_Put_Int(p,(int32)GPS_Math_Deg_To_Semi(way->lon)); p+=sizeof(int32); GPS_Util_Put_Uint(p,0); p+=sizeof(int32); - for(i=0;i<40;++i) *p++ = way->cmnt[i]; + copy_char_array(&p, way->cmnt, 40, UpperYes); + GPS_Util_Put_Float(p,way->dst); p+= sizeof(float); @@ -1631,23 +1673,22 @@ static void GPS_D101_Send(UC *data, GPS_PWay way, int32 *len) static void GPS_D102_Send(UC *data, GPS_PWay way, int32 *len) { UC *p; - int32 i; p = data; - for(i=0;i<6;++i) *p++ = way->ident[i]; + copy_char_array(&p, way->ident, 6, UpperYes); GPS_Util_Put_Int(p,(int32)GPS_Math_Deg_To_Semi(way->lat)); p+=sizeof(int32); GPS_Util_Put_Int(p,(int32)GPS_Math_Deg_To_Semi(way->lon)); p+=sizeof(int32); GPS_Util_Put_Uint(p,0); p+=sizeof(int32); - for(i=0;i<40;++i) *p++ = way->cmnt[i]; + copy_char_array(&p, way->cmnt, 40, UpperYes); GPS_Util_Put_Float(p,way->dst); p+= sizeof(float); - GPS_Util_Put_Short(p,way->smbl); + GPS_Util_Put_Short(p,(US) way->smbl); *len = 64; @@ -1668,18 +1709,10 @@ static void GPS_D102_Send(UC *data, GPS_PWay way, int32 *len) static void GPS_D103_Send(UC *data, GPS_PWay way, int32 *len) { UC *p; - int32 i; p = data; - for(i=0;i<6;++i) { - if (way->ident[i] == 0) { - memset(p, ' ', 6-i); - p+=6-i; - break; - } - *p++ = way->ident[i]; - } + copy_char_array(&p, way->ident, 6, UpperYes); GPS_Util_Put_Int(p,(int32)GPS_Math_Deg_To_Semi(way->lat)); p+=sizeof(int32); @@ -1687,10 +1720,10 @@ static void GPS_D103_Send(UC *data, GPS_PWay way, int32 *len) p+=sizeof(int32); GPS_Util_Put_Uint(p,0); p+=sizeof(int32); - for(i=0;i<40;++i) *p++ = way->cmnt[i]; + copy_char_array(&p, way->cmnt, 40, UpperYes); - *p++ = way->smbl; - *p = way->dspl; + *p++ = (UC) way->smbl; + *p = (UC) way->dspl; *len = 60; @@ -1711,11 +1744,10 @@ static void GPS_D103_Send(UC *data, GPS_PWay way, int32 *len) static void GPS_D104_Send(UC *data, GPS_PWay way, int32 *len) { UC *p; - int32 i; p = data; - for(i=0;i<6;++i) *p++ = way->ident[i]; + copy_char_array(&p, way->ident, 6, UpperYes); GPS_Util_Put_Int(p,(int32)GPS_Math_Deg_To_Semi(way->lat)); p+=sizeof(int32); GPS_Util_Put_Int(p,(int32)GPS_Math_Deg_To_Semi(way->lon)); @@ -1726,12 +1758,12 @@ static void GPS_D104_Send(UC *data, GPS_PWay way, int32 *len) * results in the comment being truncated there. So we uppercase * the entire comment. */ - for(i=0;i<40;++i) *p++ = toupper(way->cmnt[i]); + copy_char_array(&p, way->cmnt, 40, UpperYes); GPS_Util_Put_Float(p,way->dst); p+= sizeof(float); - GPS_Util_Put_Short(p,way->smbl); + GPS_Util_Put_Short(p, (int16) way->smbl); p+=sizeof(int16); *p = 3; /* display symbol with waypoint name */ @@ -1764,7 +1796,7 @@ static void GPS_D105_Send(UC *data, GPS_PWay way, int32 *len) GPS_Util_Put_Int(p,(int32)GPS_Math_Deg_To_Semi(way->lon)); p+=sizeof(int32); - GPS_Util_Put_Short(p,way->smbl); + GPS_Util_Put_Short(p, (int16) way->smbl); p+=sizeof(int16); q = (UC *) way->wpt_ident; @@ -1802,7 +1834,7 @@ static void GPS_D106_Send(UC *data, GPS_PWay way, int32 *len) GPS_Util_Put_Int(p,(int32)GPS_Math_Deg_To_Semi(way->lon)); p+=sizeof(int32); - GPS_Util_Put_Short(p,way->smbl); + GPS_Util_Put_Short(p, (int16) way->smbl); p+=sizeof(int16); q = (UC *) way->wpt_ident; @@ -1829,17 +1861,17 @@ static void GPS_D106_Send(UC *data, GPS_PWay way, int32 *len) static void GPS_D107_Send(UC *data, GPS_PWay way, int32 *len) { UC *p; - int32 i; p = data; - for(i=0;i<6;++i) *p++ = way->ident[i]; + + copy_char_array(&p, way->ident, 6, UpperYes); GPS_Util_Put_Int(p,(int32)GPS_Math_Deg_To_Semi(way->lat)); p+=sizeof(int32); GPS_Util_Put_Int(p,(int32)GPS_Math_Deg_To_Semi(way->lon)); p+=sizeof(int32); GPS_Util_Put_Uint(p,0); p+=sizeof(int32); - for(i=0;i<40;++i) *p++ = way->cmnt[i]; + copy_char_array(&p, way->cmnt, 40, UpperYes); *p++ = way->smbl; *p++ = way->dspl; @@ -1879,7 +1911,7 @@ static void GPS_D108_Send(UC *data, GPS_PWay way, int32 *len) *p++ = way->colour; *p++ = way->dspl; *p++ = 0x60; - GPS_Util_Put_Short(p,way->smbl); + GPS_Util_Put_Short(p,(US) way->smbl); p+=sizeof(int16); for(i=0;i<18;++i) *p++ = way->subclass[i]; GPS_Util_Put_Int(p,(int32)GPS_Math_Deg_To_Semi(way->lat)); @@ -1932,8 +1964,9 @@ static void GPS_D108_Send(UC *data, GPS_PWay way, int32 *len) ** @param [w] len [int32 *] packet length ** ** @return [void] +** D109's and D110's are so simlar, we handle themw with the same code. ************************************************************************/ -static void GPS_D109_Send(UC *data, GPS_PWay way, int32 *len) +static void GPS_D109_Send(UC *data, GPS_PWay way, int32 *len, int protoid) { UC *p; UC *q; @@ -1945,8 +1978,14 @@ static void GPS_D109_Send(UC *data, GPS_PWay way, int32 *len) *p++ = 0 /* way->colour*/ ; /* If non-zero, the waypoint is in invisible ink on the V. */ *p++ = way->dspl; - *p++ = 0x70; - GPS_Util_Put_Short(p,way->smbl); + if (protoid == 109) { + *p++ = 0x70; + } else if (protoid == 110) { + *p++ = 0x80; + } else { + GPS_Warning("Unknown protoid in GPS_D109_Send."); + } + GPS_Util_Put_Short(p,(US) way->smbl); p+=sizeof(int16); for(i=0;i<18;++i) *p++ = way->subclass[i]; GPS_Util_Put_Int(p,(int32)GPS_Math_Deg_To_Semi(way->lat)); @@ -1963,6 +2002,21 @@ static void GPS_D109_Send(UC *data, GPS_PWay way, int32 *len) for(i=0;i<2;++i) *p++ = way->state[i]; for(i=0;i<2;++i) *p++ = way->cc[i]; for(i=0;i<4;++i) *p++ = 0xff; /* D109 silliness for ETE */ + if (protoid == 110) { + float temp = 1.0e25f; + + GPS_Util_Put_Float(p, temp); + p += 4; + + if (way->Time_populated) { + GPS_Util_Put_Uint(p,GPS_Math_Utime_To_Gtime(way->Time)); + p+=sizeof(uint32); + } else { + for(i=0;i<4;++i) *p++ = 0xff; /* unknown time*/ + } + + for(i=0;i<2;++i) *p++ = 0x00; /* D110 category */ + } q = (UC *) way->ident; i = XMIN(51, sizeof(way->ident)); @@ -2004,7 +2058,7 @@ static void GPS_D150_Send(UC *data, GPS_PWay way, int32 *len) p = data; - for(i=0;i<6;++i) *p++ = way->ident[i]; + copy_char_array(&p, way->ident, 6, UpperYes); for(i=0;i<2;++i) *p++ = way->cc[i]; if(way->wpt_class == 7) way->wpt_class = 0; @@ -2015,13 +2069,13 @@ static void GPS_D150_Send(UC *data, GPS_PWay way, int32 *len) GPS_Util_Put_Int(p,(int32)GPS_Math_Deg_To_Semi(way->lon)); p+=sizeof(int32); - GPS_Util_Put_Short(p,way->alt); + GPS_Util_Put_Short(p,(US) way->alt); p+=sizeof(int16); - for(i=0;i<24;++i) *p++ = way->city[i]; - for(i=0;i<2;++i) *p++ = way->state[i]; - for(i=0;i<30;++i) *p++ = way->name[i]; - for(i=0;i<40;++i) *p++ = way->cmnt[i]; + copy_char_array(&p, way->city, 24, UpperYes); + copy_char_array(&p, way->state, 2, UpperYes); + copy_char_array(&p, way->name, 30, UpperYes); + copy_char_array(&p, way->cmnt, 40, UpperYes); *len = 115; @@ -2046,7 +2100,7 @@ static void GPS_D151_Send(UC *data, GPS_PWay way, int32 *len) p = data; - for(i=0;i<6;++i) *p++ = way->ident[i]; + copy_char_array(&p, way->ident, 6, UpperYes); GPS_Util_Put_Int(p,(int32)GPS_Math_Deg_To_Semi(way->lat)); p+=sizeof(int32); @@ -2054,15 +2108,15 @@ static void GPS_D151_Send(UC *data, GPS_PWay way, int32 *len) p+=sizeof(int32); GPS_Util_Put_Uint(p,0); p+=sizeof(int32); - for(i=0;i<40;++i) *p++ = way->cmnt[i]; + copy_char_array(&p, way->cmnt, 40, UpperYes); GPS_Util_Put_Float(p,way->dst); p+=sizeof(float); - for(i=0;i<30;++i) *p++ = way->name[i]; - for(i=0;i<24;++i) *p++ = way->city[i]; - for(i=0;i<2;++i) *p++ = way->state[i]; + copy_char_array(&p, way->name, 30, UpperYes); + copy_char_array(&p, way->city, 24, UpperYes); + copy_char_array(&p, way->state, 2, UpperYes); - GPS_Util_Put_Short(p,way->alt); + GPS_Util_Put_Short(p,(US) way->alt); p+=sizeof(int16); for(i=0;i<2;++i) *p++ = way->cc[i]; @@ -2095,7 +2149,7 @@ static void GPS_D152_Send(UC *data, GPS_PWay way, int32 *len) p = data; - for(i=0;i<6;++i) *p++ = way->ident[i]; + copy_char_array(&p, way->ident, 6, UpperYes); GPS_Util_Put_Int(p,(int32)GPS_Math_Deg_To_Semi(way->lat)); p+=sizeof(int32); @@ -2103,15 +2157,15 @@ static void GPS_D152_Send(UC *data, GPS_PWay way, int32 *len) p+=sizeof(int32); GPS_Util_Put_Uint(p,0); p+=sizeof(int32); - for(i=0;i<40;++i) *p++ = way->cmnt[i]; + copy_char_array(&p, way->cmnt, 40, UpperYes); GPS_Util_Put_Float(p,way->dst); p+=sizeof(float); - for(i=0;i<30;++i) *p++ = way->name[i]; - for(i=0;i<24;++i) *p++ = way->city[i]; - for(i=0;i<2;++i) *p++ = way->state[i]; + copy_char_array(&p, way->name, 30, UpperYes); + copy_char_array(&p, way->city, 24, UpperYes); + copy_char_array(&p, way->state, 2, UpperYes); - GPS_Util_Put_Short(p,way->alt); + GPS_Util_Put_Short(p,(US) way->alt); p+=sizeof(int16); for(i=0;i<2;++i) *p++ = way->cc[i]; @@ -2143,7 +2197,7 @@ static void GPS_D154_Send(UC *data, GPS_PWay way, int32 *len) p = data; - for(i=0;i<6;++i) *p++ = way->ident[i]; + copy_char_array(&p, way->ident, 6, UpperYes); GPS_Util_Put_Int(p,(int32)GPS_Math_Deg_To_Semi(way->lat)); p+=sizeof(int32); @@ -2151,15 +2205,16 @@ static void GPS_D154_Send(UC *data, GPS_PWay way, int32 *len) p+=sizeof(int32); GPS_Util_Put_Uint(p,0); p+=sizeof(int32); - for(i=0;i<40;++i) *p++ = way->cmnt[i]; + copy_char_array(&p, way->cmnt, 40, UpperYes); + GPS_Util_Put_Float(p,way->dst); p+=sizeof(float); - for(i=0;i<30;++i) *p++ = way->name[i]; - for(i=0;i<24;++i) *p++ = way->city[i]; - for(i=0;i<2;++i) *p++ = way->state[i]; + copy_char_array(&p, way->name, 30, UpperYes); + copy_char_array(&p, way->city, 24, UpperYes); + copy_char_array(&p, way->state, 2, UpperYes); - GPS_Util_Put_Short(p,way->alt); + GPS_Util_Put_Short(p,(US) way->alt); p+=sizeof(int16); for(i=0;i<2;++i) *p++ = way->cc[i]; @@ -2194,7 +2249,7 @@ static void GPS_D155_Send(UC *data, GPS_PWay way, int32 *len) p = data; - for(i=0;i<6;++i) *p++ = way->ident[i]; + copy_char_array(&p, way->ident, 6, UpperYes); GPS_Util_Put_Int(p,(int32)GPS_Math_Deg_To_Semi(way->lat)); p+=sizeof(int32); @@ -2202,15 +2257,15 @@ static void GPS_D155_Send(UC *data, GPS_PWay way, int32 *len) p+=sizeof(int32); GPS_Util_Put_Uint(p,0); p+=sizeof(int32); - for(i=0;i<40;++i) *p++ = way->cmnt[i]; + copy_char_array(&p, way->cmnt, 40, UpperYes); GPS_Util_Put_Float(p,way->dst); p+=sizeof(float); - for(i=0;i<30;++i) *p++ = way->name[i]; - for(i=0;i<24;++i) *p++ = way->city[i]; - for(i=0;i<2;++i) *p++ = way->state[i]; + copy_char_array(&p, way->name, 30, UpperYes); + copy_char_array(&p, way->city, 24, UpperYes); + copy_char_array(&p, way->state, 2, UpperYes); - GPS_Util_Put_Short(p,way->alt); + GPS_Util_Put_Short(p,(US) way->alt); p+=sizeof(int16); for(i=0;i<2;++i) *p++ = way->cc[i]; @@ -2349,7 +2404,10 @@ int32 GPS_A200_Get(const char *port, GPS_PWay **way) GPS_D108_Get(&((*way)[i]),rec->data); break; case pD109: - GPS_D109_Get(&((*way)[i]),rec->data); + GPS_D109_Get(&((*way)[i]),rec->data,109); + break; + case pD110: + GPS_D109_Get(&((*way)[i]),rec->data,110); break; case pD150: GPS_D150_Get(&((*way)[i]),rec->data); @@ -2539,7 +2597,10 @@ int32 GPS_A201_Get(const char *port, GPS_PWay **way) GPS_D108_Get(&((*way)[i]),rec->data); break; case pD109: - GPS_D109_Get(&((*way)[i]),rec->data); + GPS_D109_Get(&((*way)[i]),rec->data,109); + break; + case pD110: + GPS_D109_Get(&((*way)[i]),rec->data,110); break; case pD150: GPS_D150_Get(&((*way)[i]),rec->data); @@ -2619,7 +2680,7 @@ int32 GPS_A200_Send(const char *port, GPS_PWay *way, int32 n) if(!(tra = GPS_Packet_New()) || !(rec = GPS_Packet_New())) return MEMORY_ERROR; - GPS_Util_Put_Short(data,n); + GPS_Util_Put_Short(data,(US) n); GPS_Make_Packet(&tra, LINK_ID[gps_link_type].Pid_Records, data,2); if(!GPS_Write_Packet(fd,tra)) @@ -2708,7 +2769,7 @@ int32 GPS_A200_Send(const char *port, GPS_PWay *way, int32 n) } - GPS_Make_Packet(&tra, method, data,len); + GPS_Make_Packet(&tra, method, data,(US) len); if(!GPS_Write_Packet(fd,tra)) return gps_errno; @@ -2768,7 +2829,7 @@ int32 GPS_A201_Send(const char *port, GPS_PWay *way, int32 n) if(!(tra = GPS_Packet_New()) || !(rec = GPS_Packet_New())) return MEMORY_ERROR; - GPS_Util_Put_Short(data,n); + GPS_Util_Put_Short(data,(US) n); GPS_Make_Packet(&tra, LINK_ID[gps_link_type].Pid_Records, data,2); if(!GPS_Write_Packet(fd,tra)) @@ -2850,7 +2911,10 @@ int32 GPS_A201_Send(const char *port, GPS_PWay *way, int32 n) GPS_D108_Send(data,way[i],&len); break; case pD109: - GPS_D109_Send(data,way[i],&len); + GPS_D109_Send(data,way[i],&len, 109); + break; + case pD110: + GPS_D109_Send(data,way[i],&len, 110); break; case pD150: GPS_D150_Send(data,way[i],&len); @@ -2874,7 +2938,7 @@ int32 GPS_A201_Send(const char *port, GPS_PWay *way, int32 n) } - GPS_Make_Packet(&tra, method, data,len); + GPS_Make_Packet(&tra, method, data,(US) len); if(!GPS_Write_Packet(fd,tra)) return gps_errno; @@ -2972,7 +3036,7 @@ static void GPS_D202_Get(GPS_PWay *way, UC *s) p=s; - (*way)->rte_prot = 201; + (*way)->rte_prot = 202; #if 0 /* D202 has only a null terminated string for rte_ident */ (*way)->rte_num = *p++; @@ -3106,7 +3170,7 @@ static void GPS_D210_Send(UC *data, GPS_PWay way, int32 *len) p = data; - GPS_Util_Put_Short(p,way->rte_link_class); + GPS_Util_Put_Short(p,(US) way->rte_link_class); p+=sizeof(int16); for(i=0;i<18;++i) *p++ = way->rte_link_subclass[i]; @@ -3389,7 +3453,7 @@ int32 GPS_A300_Send(const char *port, GPS_PTrack *trk, int32 n) if(!(tra = GPS_Packet_New()) || !(rec = GPS_Packet_New())) return MEMORY_ERROR; - GPS_Util_Put_Short(data,n); + GPS_Util_Put_Short(data,(US) n); GPS_Make_Packet(&tra, LINK_ID[gps_link_type].Pid_Records, data,2); if(!GPS_Write_Packet(fd,tra)) @@ -3414,7 +3478,7 @@ int32 GPS_A300_Send(const char *port, GPS_PTrack *trk, int32 n) } GPS_Make_Packet(&tra, LINK_ID[gps_link_type].Pid_Trk_Data, - data,len); + data,(US) len); if(!GPS_Write_Packet(fd,tra)) return gps_errno; @@ -3484,7 +3548,7 @@ int32 GPS_A301_Send(const char *port, GPS_PTrack *trk, int32 n) if(!(tra = GPS_Packet_New()) || !(rec = GPS_Packet_New())) return MEMORY_ERROR; - GPS_Util_Put_Short(data,n); + GPS_Util_Put_Short(data,(US) n); GPS_Make_Packet(&tra, LINK_ID[gps_link_type].Pid_Records, data,2); if(!GPS_Write_Packet(fd,tra)) @@ -3535,7 +3599,7 @@ int32 GPS_A301_Send(const char *port, GPS_PTrack *trk, int32 n) } - GPS_Make_Packet(&tra, method, data,len); + GPS_Make_Packet(&tra, method, data,(US) len); if(!GPS_Write_Packet(fd,tra)) return gps_errno; @@ -3765,7 +3829,6 @@ void GPS_D310_Get(GPS_PTrack *trk, UC *s) void GPS_D311_Get(GPS_PTrack *trk, UC *s) { UC *p; - UC *q; short identifier; p=s; @@ -4031,7 +4094,10 @@ int32 GPS_A400_Get(const char *port, GPS_PWay **way) GPS_D108_Get(&((*way)[i]),rec->data); break; case pD109: - GPS_D109_Get(&((*way)[i]),rec->data); + GPS_D109_Get(&((*way)[i]),rec->data,109); + break; + case pD110: + GPS_D109_Get(&((*way)[i]),rec->data,110); break; case pD450: GPS_D450_Get(&((*way)[i]),rec->data); @@ -4112,7 +4178,7 @@ int32 GPS_A400_Send(const char *port, GPS_PWay *way, int32 n) return MEMORY_ERROR; - GPS_Util_Put_Short(data,n); + GPS_Util_Put_Short(data,(US) n); GPS_Make_Packet(&tra, LINK_ID[gps_link_type].Pid_Records, data,2); if(!GPS_Write_Packet(fd,tra)) @@ -4176,7 +4242,7 @@ int32 GPS_A400_Send(const char *port, GPS_PWay *way, int32 n) } GPS_Make_Packet(&tra, LINK_ID[gps_link_type].Pid_Prx_Wpt_Data, - data,len); + data,(US) len); if(!GPS_Write_Packet(fd,tra)) return gps_errno; @@ -4417,7 +4483,7 @@ static void GPS_D450_Send(UC *data, GPS_PWay way, int32 *len) p = data; - GPS_Util_Put_Short(p,way->idx); + GPS_Util_Put_Short(p,(US) way->idx); p+=sizeof(int16); for(i=0;i<6;++i) *p++ = way->ident[i]; @@ -4429,7 +4495,7 @@ static void GPS_D450_Send(UC *data, GPS_PWay way, int32 *len) GPS_Util_Put_Int(p,(int32)GPS_Math_Deg_To_Semi(way->lon)); p+=sizeof(int32); - GPS_Util_Put_Short(p,way->alt); + GPS_Util_Put_Short(p,(US) way->alt); p+=sizeof(int16); for(i=0;i<24;++i) *p++ = way->city[i]; @@ -4569,7 +4635,7 @@ int32 GPS_A500_Send(const char *port, GPS_PAlmanac *alm, int32 n) return MEMORY_ERROR; - GPS_Util_Put_Short(data,n); + GPS_Util_Put_Short(data,(US) n); GPS_Make_Packet(&tra, LINK_ID[gps_link_type].Pid_Records, data,2); if(!GPS_Write_Packet(fd,tra)) @@ -4621,7 +4687,7 @@ int32 GPS_A500_Send(const char *port, GPS_PAlmanac *alm, int32 n) } GPS_Make_Packet(&tra, LINK_ID[gps_link_type].Pid_Almanac_Data, - data,len); + data,(US) len); if(!GPS_Write_Packet(fd,tra)) return gps_errno; @@ -5313,9 +5379,9 @@ void GPS_D600_Send(GPS_PPacket *packet, time_t Time) *p++ = ts->tm_mon+1; *p++ = ts->tm_mday; - GPS_Util_Put_Short(p,ts->tm_year+1900); + GPS_Util_Put_Short(p,(US) (ts->tm_year+1900)); p+=2; - GPS_Util_Put_Short(p,ts->tm_hour); + GPS_Util_Put_Short(p,(US) ts->tm_hour); p+=2; *p++ = ts->tm_min; diff --git a/jeeps/gpscom.c b/jeeps/gpscom.c index 9cfca0331..b3d6b3e05 100644 --- a/jeeps/gpscom.c +++ b/jeeps/gpscom.c @@ -84,7 +84,7 @@ int32 GPS_Command_Off(const char *port) ** @return [int32] number of waypoint entries ************************************************************************/ -int32 GPS_Command_Get_Waypoint(const char *port, GPS_PWay **way, int (*cb)()) +int32 GPS_Command_Get_Waypoint(const char *port, GPS_PWay **way, int (*cb)(int, struct GPS_SWay **)) { int32 ret=0; @@ -114,7 +114,7 @@ int32 GPS_Command_Get_Waypoint(const char *port, GPS_PWay **way, int (*cb)()) ** @return [int32] success ************************************************************************/ -int32 GPS_Command_Send_Waypoint(const char *port, GPS_PWay *way, int32 n, int (*cb)()) +int32 GPS_Command_Send_Waypoint(const char *port, GPS_PWay *way, int32 n, int (*cb)(struct GPS_SWay **)) { int32 ret=0; diff --git a/jeeps/gpscom.h b/jeeps/gpscom.h index 0d8415736..e8bbe1d2a 100644 --- a/jeeps/gpscom.h +++ b/jeeps/gpscom.h @@ -28,8 +28,8 @@ int32 GPS_Command_Send_Almanac(const char *port, GPS_PAlmanac *alm, int32 n); int32 GPS_Command_Get_Track(const char *port, GPS_PTrack **trk); int32 GPS_Command_Send_Track(const char *port, GPS_PTrack *trk, int32 n); -int32 GPS_Command_Get_Waypoint(const char *port, GPS_PWay **way,int (*cb)()); -int32 GPS_Command_Send_Waypoint(const char *port, GPS_PWay *way, int32 n, int (*cb)()); +int32 GPS_Command_Get_Waypoint(const char *port, GPS_PWay **way,int (*cb)(int, struct GPS_SWay **)); +int32 GPS_Command_Send_Waypoint(const char *port, GPS_PWay *way, int32 n, int (*cb)(struct GPS_SWay **)); int32 GPS_Command_Get_Proximity(const char *port, GPS_PWay **way); int32 GPS_Command_Send_Proximity(const char *port, GPS_PWay *way, int32 n); diff --git a/jeeps/gpsinput.c b/jeeps/gpsinput.c index ad3e99b6e..89d0797c8 100644 --- a/jeeps/gpsinput.c +++ b/jeeps/gpsinput.c @@ -422,7 +422,11 @@ int32 GPS_Input_Get_Waypoint(GPS_PWay **way, FILE *inf) if(ret<0) return gps_errno; break; case 109: - ret = GPS_Input_Get_D109(&((*way)[i]),inf); + ret = GPS_Input_Get_D109(&((*way)[i]),inf, 109); + if(ret<0) return gps_errno; + break; + case 110: + ret = GPS_Input_Get_D109(&((*way)[i]),inf, 110); if(ret<0) return gps_errno; break; case 150: @@ -550,7 +554,11 @@ int32 GPS_Input_Get_Proximity(GPS_PWay **way, FILE *inf) if(ret<0) return gps_errno; break; case 109: - ret = GPS_Input_Get_D109(&((*way)[i]),inf); + ret = GPS_Input_Get_D109(&((*way)[i]),inf, 109); + if(ret<0) return gps_errno; + break; + case 110: + ret = GPS_Input_Get_D109(&((*way)[i]),inf, 110); if(ret<0) return gps_errno; break; case 450: @@ -1070,8 +1078,9 @@ static int32 GPS_Input_Get_D108(GPS_PWay *way, FILE *inf) ** @param [r] inf [FILE *] stream ** ** @return [int32] number of entries +** D109's and D110's are so similar, we handle both with the same function. ************************************************************************/ -static int32 GPS_Input_Get_D109(GPS_PWay *way, FILE *inf) +static int32 GPS_Input_Get_D109(GPS_PWay *way, FILE *inf, int protonum) { char s[GPS_ARB_LEN]; char *p; diff --git a/jeeps/gpslibusb.c b/jeeps/gpslibusb.c index b8c5868b4..d62dd9565 100644 --- a/jeeps/gpslibusb.c +++ b/jeeps/gpslibusb.c @@ -22,6 +22,7 @@ #include +#include #include #include "gps.h" #include "garminusb.h" @@ -32,9 +33,12 @@ * sloppy about not obeying packet boundries. If this is too high, the * multiple packets responding to the device inquriy will be glommed into * one packet and we'll misparse them. If it's too low, we'll get partially - * satisfied reads. + * satisfied reads. It turns out this isn't terrible becuase we still end + * up with DLE boundings and the upper layers (which are used to doing frame + * coalescion into packets anyway becuase of their serial background) will + * compensate. */ -#define TMOUT_I 0015 /* Milliseconds to timeout intr pipe access. */ +#define TMOUT_I 0100 /* Milliseconds to timeout intr pipe access. */ int gusb_intr_in_ep; int gusb_bulk_out_ep; @@ -50,7 +54,7 @@ static void garmin_usb_syncup(void); gusb_init(void) { -//usb_set_debug(99); +// usb_set_debug(99); usb_init(); usb_find_busses(); usb_find_devices(); @@ -60,7 +64,7 @@ gusb_init(void) return 1; } -dump(char *msg, const unsigned char *in, int r) +static void dump(char *msg, const unsigned char *in, int r) { int i; printf("%s: %d\n", msg, r); @@ -79,49 +83,19 @@ gusb_cmd_send(const garmin_usb_packet *opkt, size_t sz) { int r; - r = usb_bulk_write(udev, gusb_bulk_out_ep, &opkt->dbuf, sz, TMOUT_I); - dump ("Sent", &opkt->dbuf[0], r); - if (r != sz) { - fprintf(stderr, "Bad cmdsend\n"); + r = usb_bulk_write(udev, gusb_bulk_out_ep, (char *)(void *)opkt->dbuf, sz, TMOUT_I); + if (gps_show_bytes) { + dump ("Sent", &opkt->dbuf[0], r); } -} -#if 0 -int -gusb_cmd_get(garmin_usb_packet *ibuf, size_t sz) -{ - int rv = 0; - unsigned char *obuf = &ibuf->dbuf; - unsigned char *buf = obuf; - - while (sz) { - int r; - /* - * Since Garmin stupidly put bulk data on an interrupt pipe - * with an absurdly tiny buffer, we have to coalesce reads - * and we have to be fast about getting them. (High speed - * polling totally misses the point of USB...) - */ - - r = usb_interrupt_read(udev, gusb_intr_in_ep, buf, sz, TMOUT_I); - printf("Read: %d/%d \n", r, sz); - if (r > 0) { - buf += r; - rv += r; - sz -= r; - } - if (r < 0) return rv; - /* - * A zero length read AFTER a successful read means we're - * done. - */ - if (r == 0 && rv) { - break; + if (r != sz) { + fprintf(stderr, "Bad cmdsend r %d sz %d\n", r, sz); + if (r < 0) { + fatal("usb_bulk_write failed. '%s'", + usb_strerror()); } } - dump("completed intr Got", obuf, rv); - return rv; + return r; } -#else int gusb_cmd_get(garmin_usb_packet *ibuf, size_t sz) @@ -129,7 +103,7 @@ gusb_cmd_get(garmin_usb_packet *ibuf, size_t sz) unsigned char *buf = &ibuf->dbuf[0]; unsigned char *obuf = buf; int r = -1, tsz = 0; - while (r <= 0) + r = usb_interrupt_read(udev, gusb_intr_in_ep, buf, sz, TMOUT_I); tsz = r; @@ -149,27 +123,35 @@ gusb_cmd_get(garmin_usb_packet *ibuf, size_t sz) } return (r); - - } -#endif void garmin_usb_teardown(void) { if (udev) { - fprintf(stderr, "Tearing down\n"); usb_release_interface(udev, 0); usb_close(udev); udev = NULL; } } +void garmin_usb_start(struct usb_device *dev) { - int ret; int i; - char ibuf[4096]; + + if (udev) return; + + /* + * Linux _requires_ the reset. OSX doesn't work if we DO reset it. + * I really should study this more, but for now, we'll just avoid the + * reset on Apple's OSX. + */ +#if !defined (__APPLE__) + udev = usb_open(dev); + usb_reset(udev); + usb_close(udev); +#endif /* APPLE */ udev = usb_open(dev); atexit(garmin_usb_teardown); @@ -177,15 +159,16 @@ garmin_usb_start(struct usb_device *dev) /* * Hrmph. No iManufacturer or iProduct headers.... */ - if (usb_claim_interface(udev, 0) < 0) { - abort(); + if (usb_set_configuration(udev, 1) < 0) { + fatal("usb_set_configuration failed"); } - if (usb_set_configuration(udev, 1) < 0) { - abort(); + if (usb_claim_interface(udev, 0) < 0) { +// abort(); } + for (i = 0; i < dev->config->interface->altsetting->bNumEndpoints; i++) { struct usb_endpoint_descriptor * ep; ep = &dev->config->interface->altsetting->endpoint[i]; @@ -202,20 +185,19 @@ garmin_usb_start(struct usb_device *dev) gusb_intr_in_ep = EA(ep->bEndpointAddress); break; } - } -//printf("Bulk in: %d\n", gusb_bulk_in_ep); -//printf("Bulk out: %d\n", gusb_bulk_out_ep); -//printf("intr in: %d\n", gusb_intr_in_ep); - - garmin_usb_syncup(); + } -// fprintf(stdout, "====================================================\n"); + /* + * Zero is the configuration endpoint, so if we made it through + * that loop without non-zero values for all three, we're hosed. + */ + if (gusb_intr_in_ep && gusb_bulk_in_ep && gusb_bulk_out_ep) { + garmin_usb_syncup(); + } else { + fatal("Could not identify endpoints on USB device.\nFound endpoints Intr In %d Bulk Out %d Bulk In %d\n", gusb_intr_in_ep, gusb_bulk_out_ep, gusb_bulk_in_ep); + } return; - usb_release_interface(udev, 0); - usb_reset(udev); - usb_close(udev); -exit(1); } void @@ -223,12 +205,6 @@ garmin_usb_syncup(void) { int maxct = 5; int maxtries; - char ibuf[4096]; -#if 0 - usb_clear_halt(udev, gusb_intr_in_ep); - usb_clear_halt(udev, gusb_bulk_out_ep); - usb_clear_halt(udev, gusb_bulk_in_ep); -#endif for (maxtries = maxct; maxtries; maxtries--) { @@ -241,7 +217,9 @@ garmin_usb_syncup(void) if ((le_read16(iresp.gusb_pkt.pkt_id) == 6) && (le_read32(iresp.gusb_pkt.datasz) == 4)) { - fprintf(stderr, "Synced in %d\n", maxct - maxtries); + if (gps_show_bytes) { + fprintf(stderr, "Synced in %d\n", maxct - maxtries); + } // fprintf(stderr, "Unit number %u\n", iresp[15] << 24 | iresp[14] << 16 | iresp[13] << 8 | iresp[12]); return; } @@ -253,8 +231,8 @@ return; static void garmin_usb_scan(void) { + int initted = 0; struct usb_bus *bus; - int c, i, a; for (bus = busses; bus; bus = bus->next) { struct usb_device *dev; @@ -265,10 +243,15 @@ void garmin_usb_scan(void) * we just take the easy way out for now. */ if (dev->descriptor.idVendor == GARMIN_VID) { - garmin_usb_start(dev); + garmin_usb_start(dev); + initted++; } } } + + if (0 == initted) { + fatal("Found no Garmin USB devices.\n"); + } } #endif /* !defined(NO_USB) */ diff --git a/jeeps/gpsmem.c b/jeeps/gpsmem.c index b351a0a43..f5a893459 100644 --- a/jeeps/gpsmem.c +++ b/jeeps/gpsmem.c @@ -39,7 +39,7 @@ GPS_PPacket GPS_Packet_New(void) { GPS_PPacket ret; - int hdr_size = gps_is_usb ? sizeof(garmin_usb_packet) : sizeof(GPS_OPacket) ; + int hdr_size = sizeof(GPS_OPacket) ; if(!(ret=(GPS_PPacket )malloc(hdr_size))) { @@ -296,7 +296,7 @@ GPS_PWay GPS_Way_New(void) void GPS_Way_Del(GPS_PWay *thys) { - free((void *)*thys); + xfree((void *)*thys); return; } diff --git a/jeeps/gpsport.h b/jeeps/gpsport.h index 040efd2e7..dd23cc401 100644 --- a/jeeps/gpsport.h +++ b/jeeps/gpsport.h @@ -2,15 +2,14 @@ * For portability any '32' type must be 32 bits * and '16' type must be 16 bits */ -typedef unsigned char UC; -typedef short int16; -typedef unsigned short uint16; -typedef uint16 US; -#if defined(__alpha) -typedef int int32; -typedef unsigned int uint32; -#else -typedef long int32; -typedef unsigned long uint32; -#endif +/* Since GPSBabel already has an integer size abstraction layer and + * defs.h includes gbtypes.h before this file, just use that. + */ + +typedef unsigned char UC; +typedef gbuint16 US; +typedef gbuint16 uint16; +typedef gbint16 int16; +typedef gbuint32 uint32; +typedef gbint32 int32; diff --git a/jeeps/gpsprot.c b/jeeps/gpsprot.c index 50606b7d2..812437092 100644 --- a/jeeps/gpsprot.c +++ b/jeeps/gpsprot.c @@ -63,7 +63,7 @@ struct LINKDATA LINK_ID[3]= struct GPS_MODEL_PROTOCOL GPS_MP[]= { - { 7,pL001,pA010,pA100,pD100,pA200,pD200,-1,-1,-1,-1, + { 7,pL001,pA010,pA100,pD100,pA200,pD200,-1,-1,-1,-1,-1, pA500,pD500 }, { 13,pL001,pA010,pA100,pD100,pA200,pD200,pD100,pA300,pD300,pA400,pD400, diff --git a/jeeps/gpsprot.h b/jeeps/gpsprot.h index 8c807bf16..6a9e75bc1 100644 --- a/jeeps/gpsprot.h +++ b/jeeps/gpsprot.h @@ -141,6 +141,7 @@ int32 gps_pvt_transfer; #define pD107 107 #define pD108 108 #define pD109 109 +#define pD110 110 #define pD150 150 #define pD151 151 #define pD152 152 @@ -246,7 +247,7 @@ int32 gps_link_type; struct GPS_MODEL_PROTOCOL { - int32 id; + US id; int32 link; int32 command; int32 wayptt; diff --git a/jeeps/gpsread.c b/jeeps/gpsread.c index d37fe6f3e..2d2f2d153 100644 --- a/jeeps/gpsread.c +++ b/jeeps/gpsread.c @@ -22,6 +22,7 @@ ** Boston, MA 02111-1307, USA. ********************************************************************/ #include "gps.h" +#include "gpsusbint.h" #include #include #include diff --git a/jeeps/gpsread.h b/jeeps/gpsread.h index 138cc5866..5abd56cfa 100644 --- a/jeeps/gpsread.h +++ b/jeeps/gpsread.h @@ -12,6 +12,7 @@ extern "C" time_t GPS_Time_Now(void); int32 GPS_Packet_Read(int32 fd, GPS_PPacket *packet); +int32 GPS_Packet_Read_usb(int32 fd, GPS_PPacket *packet); int32 GPS_Get_Ack(int32 fd, GPS_PPacket *tra, GPS_PPacket *rec); int32 ajb(int32 fd); diff --git a/jeeps/gpssend.c b/jeeps/gpssend.c index c4b299d7a..b32ba2a27 100644 --- a/jeeps/gpssend.c +++ b/jeeps/gpssend.c @@ -22,8 +22,11 @@ ** Boston, MA 02111-1307, USA. ********************************************************************/ #include "gps.h" +#include "gpsusbint.h" + #include #include +#include /* @func GPS_Make_Packet *********************************************** @@ -58,7 +61,7 @@ void GPS_Make_Packet(GPS_PPacket *packet, UC type, UC *data, int16 n) (*packet)->dle = DLE; (*packet)->edle = DLE; (*packet)->etx = ETX; - (*packet)->n = n; + (*packet)->n = (UC) n; (*packet)->type = type; (*packet)->bytes = 0; diff --git a/jeeps/gpsserial.c b/jeeps/gpsserial.c index 60b62545f..4883b93a3 100644 --- a/jeeps/gpsserial.c +++ b/jeeps/gpsserial.c @@ -23,6 +23,7 @@ ** Boston, MA 02111-1307, USA. ********************************************************************/ #include "gps.h" +#include "garminusb.h" #include #include #include @@ -61,6 +62,11 @@ char *rxdata[] = { * internal. This means we ignore that 'fd' number that gets passed in. */ +static HANDLE comport; + +/* + * Display an error from the serial subsystem. + */ void GPS_Serial_Error(char *hdr) { char msg[200]; @@ -76,8 +82,6 @@ void GPS_Serial_Error(char *hdr) GPS_Error(msg); } -static HANDLE comport; - int32 GPS_Serial_On(const char *port, int32 *fd) { DCB tio; @@ -135,6 +139,7 @@ int32 GPS_Serial_On(const char *port, int32 *fd) * (i.e. cable unplugged, unit not turned on) values. */ GetCommTimeouts (comport, &timeout); + timeout.ReadIntervalTimeout = 1000; /*like vtime. In MS. */ timeout.ReadTotalTimeoutMultiplier = 1000; timeout.ReadTotalTimeoutConstant = 1000; @@ -164,12 +169,27 @@ int32 GPS_Serial_Off(const char *port, int32 fd) int32 GPS_Serial_Chars_Ready(int32 fd) { - return 1; + COMSTAT lpStat; + DWORD lpErrors; + + ClearCommError(comport, &lpErrors, &lpStat); + return (lpStat.cbInQue > 0); } int32 GPS_Serial_Wait(int32 fd) { - return 1; + + if (gps_is_usb) return 1; + + /* Wait a short time before testing if data is ready. + * The GPS II, in particular, has a noticable time responding + * with a response to the device inquiry and if we give up on this + * too soon, we fail to read the response to the A001 packet and + * blow our state machines when it starts streaming the capabiilties + * response packet. + */ + Sleep(usecDELAY / 1000); + return GPS_Serial_Chars_Ready(fd); } int32 GPS_Serial_Flush(int32 fd) @@ -180,8 +200,19 @@ int32 GPS_Serial_Flush(int32 fd) int32 GPS_Serial_Write(int32 ignored, const void *obuf, int size) { DWORD len; + + /* + * Unbelievably, the Keyspan PDA serial driver 3.2, a "Windows + * Certified driver", will crash the OS on a write of zero bytes. + * We get such writes from upstream when there are zero payload + * bytes. SO we trap those here to stop Keyspan & Windows from + * nuking the system. + */ + if (size == 0) { + return 0; + } WriteFile (comport, obuf, size, &len, NULL); - if (len != size) { + if (len != (DWORD) size) { fatal ("Write error. Wrote %d of %d bytes.", len, size); } return len; @@ -221,8 +252,10 @@ static struct termios gps_ttysave; int32 GPS_Serial_Savetty(const char *port) { int32 fd; + + if (gps_is_usb) return 1; - if((fd = open(port, O_RDWR|O_NDELAY))==-1) + if((fd = open(port, O_RDWR))==-1) { perror("open"); gps_errno = SERIAL_ERROR; @@ -238,7 +271,6 @@ int32 GPS_Serial_Savetty(const char *port) return 0; } - if(!GPS_Serial_Close(fd,port)) { gps_errno = SERIAL_ERROR; @@ -262,8 +294,10 @@ int32 GPS_Serial_Savetty(const char *port) int32 GPS_Serial_Restoretty(const char *port) { int32 fd; + + if (gps_is_usb) return 1; - if((fd = open(port, O_RDWR|O_NDELAY))==-1) + if((fd = open(port, O_RDWR))==-1) { perror("open"); gps_errno = HARDWARE_ERROR; @@ -312,7 +346,6 @@ int32 GPS_Serial_Open(int32 *fd, const char *port) return 0; } - if(tcgetattr(*fd,&tty)==-1) { perror("tcgetattr"); @@ -385,6 +418,7 @@ int32 GPS_Serial_Write(int32 handle, const void *obuf, int size) ************************************************************************/ int32 GPS_Serial_Flush(int32 fd) { + if (gps_is_usb) return 1; if(tcflush(fd,TCIOFLUSH)) { @@ -411,6 +445,8 @@ int32 GPS_Serial_Flush(int32 fd) int32 GPS_Serial_Close(int32 fd, const char *port) { + if (gps_is_usb) return 1; + if(close(fd)==-1) { perror("close"); @@ -449,7 +485,7 @@ int32 GPS_Serial_Chars_Ready(int32 fd) FD_SET(fd,&rec); t.tv_sec = 0; - t.tv_usec = 0; + t.tv_usec = 1000; (void) select(fd+1,&rec,NULL,NULL,&t); if(FD_ISSET(fd,&rec)) return 1; diff --git a/jeeps/gpsserial.h b/jeeps/gpsserial.h index 1849cd01c..7d3958d48 100644 --- a/jeeps/gpsserial.h +++ b/jeeps/gpsserial.h @@ -24,6 +24,7 @@ int32 GPS_Serial_Flush(int32 fd); int32 GPS_Serial_On_NMEA(const char *port, int32 *fd); int32 GPS_Serial_Read(int32 ignored, void *ibuf, int size); int32 GPS_Serial_Write(int32 ignored, const void *obuf, int size); +void GPS_Serial_Error(char *hdr); #endif diff --git a/jeeps/gpsusbint.h b/jeeps/gpsusbint.h new file mode 100644 index 000000000..3a0e00137 --- /dev/null +++ b/jeeps/gpsusbint.h @@ -0,0 +1,27 @@ +/* + Definitions for internal functions of Garmin USB implementation. + These symbols should not be publicly used. They're "friend" functions + of USB details internal to jeeps. + + Copyright (C) 2005 Robert Lipe, robertlipe@usa.net + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + + */ + +int32 GPS_Packet_Read_usb(int32 fd, GPS_PPacket *packet); +void GPS_Make_Packet_usb(GPS_PPacket *packet, UC type, UC *data, int16 n); +int32 GPS_Write_Packet_usb(int32 fd, GPS_PPacket packet); + diff --git a/jeeps/gpsusbread.c b/jeeps/gpsusbread.c index 6c9284dec..cff319a23 100644 --- a/jeeps/gpsusbread.c +++ b/jeeps/gpsusbread.c @@ -18,15 +18,14 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA */ - +#include #include "gps.h" #include "garminusb.h" +#include "gpsusbint.h" int32 GPS_Packet_Read_usb(int32 fd, GPS_PPacket *packet) { int32 n; - UC u; - UC *p; int32 i; int32 payload_size; const char *m1; @@ -56,7 +55,7 @@ int32 GPS_Packet_Read_usb(int32 fd, GPS_PPacket *packet) */ (*packet)->type = le_read16(&pkt.gusb_pkt.pkt_id); payload_size = le_read32(&pkt.gusb_pkt.datasz); - (*packet)->n = payload_size; + (*packet)->n = (UC) payload_size; memcpy((*packet)->data, &pkt.gusb_pkt.databuf, payload_size); return payload_size; } diff --git a/jeeps/gpsusbsend.c b/jeeps/gpsusbsend.c index 89fce642f..8e0877a45 100644 --- a/jeeps/gpsusbsend.c +++ b/jeeps/gpsusbsend.c @@ -23,33 +23,39 @@ #include #include #include "garminusb.h" +#include "gpsusbint.h" - -void GPS_Make_Packet_usb(GPS_PPacket *packet, UC type, UC *data, int16 n) +void +GPS_Make_Packet_usb(GPS_PPacket *packet, UC type, UC *data, int16 n) { - garmin_usb_packet **up = (garmin_usb_packet**) packet; - - /* - * This is a little tacky that we're stuffing a garmin_usb_packet - * into a GPS_PPacket, but the packet is big enough and we have only - * a few places that really peek into this structure anyway... - */ - memset(*up, 0, sizeof **packet); - (*up)->gusb_pkt.type = 0x14; /* Garmin protocol layer */ - le_write16((*up)->gusb_pkt.pkt_id, type); - le_write32((*up)->gusb_pkt.datasz, n); - memcpy(&(*up)->gusb_pkt.databuf, data, n); - - return; + /* + * For the USB case, it's a little tacky that we just copy + * the params into *packet, but we really don't have any manipulations + * to do here. They're done in send_packet in order to keep the + * contents of *packet identical for the serial and USB cases. + */ + + (*packet)->type = type; + memcpy((*packet)->data, data, n); + (*packet)->n = (UC) n; + + return; } int32 GPS_Write_Packet_usb(int32 fd, GPS_PPacket packet) { - size_t ret, sz; + garmin_usb_packet gp = {0}; + - garmin_usb_packet *gp = (garmin_usb_packet*) packet; - sz = le_read32(gp->gusb_pkt.datasz); + /* + * Take the "portable" GPS_Packet data and put them into + * the USB packet that we will put on the wire. + */ + gp.gusb_pkt.type = 0x14; + le_write16(&gp.gusb_pkt.pkt_id, packet->type); + le_write32(&gp.gusb_pkt.datasz, packet->n ); + memcpy(&gp.gusb_pkt.databuf, packet->data, packet->n); - return gusb_cmd_send(gp, sz + 12); + return gusb_cmd_send(&gp, packet->n + 12); } diff --git a/jeeps/gpsusbwin.c b/jeeps/gpsusbwin.c index 21cd9b5d9..44f15ddda 100644 --- a/jeeps/gpsusbwin.c +++ b/jeeps/gpsusbwin.c @@ -83,19 +83,20 @@ gusb_open(const char *pname) // } } - hdevinfo = SetupDiGetClassDevs( &GARMIN_GUID, NULL, NULL, + hdevinfo = SetupDiGetClassDevs( (GUID *) &GARMIN_GUID, NULL, NULL, DIGCF_PRESENT|DIGCF_INTERFACEDEVICE); if (hdevinfo == INVALID_HANDLE_VALUE) { - fatal("XXX"); + GPS_Serial_Error("SetupDiGetClassDevs failed"); return 0; } /* Get the device associated with this index. */ devinterface.cbSize = sizeof(SP_INTERFACE_DEVICE_DATA); - if (!SetupDiEnumDeviceInterfaces(hdevinfo, NULL, &GARMIN_GUID, + if (!SetupDiEnumDeviceInterfaces(hdevinfo, NULL, (GUID *) &GARMIN_GUID, 0, &devinterface)) { - fatal("blah"); + GPS_Serial_Error("SetupDiEnumDeviceInterfaces"); + warning("Is the unit powered up and connected?"); return 0; } @@ -107,7 +108,8 @@ gusb_open(const char *pname) devinfo.cbSize = sizeof(SP_DEVINFO_DATA); if (!SetupDiGetDeviceInterfaceDetail(hdevinfo, &devinterface, pdd, size, NULL, &devinfo)) { - fatal("ZZZ"); + GPS_Serial_Error("SetupDiGetDeviceInterfaceDetail"); + return 0; } /* Whew. All that just to get something we can open... */ @@ -117,7 +119,7 @@ gusb_open(const char *pname) 0, NULL, OPEN_EXISTING, 0, NULL ); if (usb_handle == INVALID_HANDLE_VALUE) { GPS_Serial_Error("CreateFile failed"); - fatal("CreateFile"); + return 0; } if(!DeviceIoControl(usb_handle, IOCTL_GARMIN_USB_BULK_OUT_PACKET_SIZE, NULL, 0, @@ -171,13 +173,14 @@ gusb_close(const char *portname) usb_handle = INVALID_HANDLE_VALUE; #endif } + return 0; } int gusb_cmd_get(garmin_usb_packet *ibuf, size_t sz) { DWORD rxed = GARMIN_USB_INTERRUPT_DATA_SIZE; - unsigned char *buf = &ibuf->dbuf; + unsigned char *buf = (unsigned char *) &ibuf->dbuf; int i; int tsz=0; unsigned char *obuf = buf; @@ -192,7 +195,7 @@ gusb_cmd_get(garmin_usb_packet *ibuf, size_t sz) fatal("ioctl"); } buf += rxed; - sz =- rxed; + sz -= rxed; tsz += rxed; if (rxed < GARMIN_USB_INTERRUPT_DATA_SIZE) { break; @@ -219,7 +222,7 @@ gusb_cmd_send(const garmin_usb_packet *opkt, size_t sz) { DWORD rsz; size_t i; - unsigned char *obuf = &opkt->dbuf; + unsigned char *obuf = (unsigned char *) &opkt->dbuf; const char *m1, *m2; /* The spec warns us about making writes an exact multiple @@ -253,7 +256,7 @@ gusb_cmd_send(const garmin_usb_packet *opkt, size_t sz) static char * id_unit(void) { -static const char oid[12] = {20, 0, 0, 0, 0xfe, 0, 0, 0, 0, 0, 0, 0}; +static const unsigned char oid[12] = {20, 0, 0, 0, 0xfe, 0, 0, 0, 0, 0, 0, 0}; /* * Identify the unit before getting into all the protocol gunk. * We get two packets back, but we discard the protocol array diff --git a/kml.c b/kml.c new file mode 100644 index 000000000..606e5e29d --- /dev/null +++ b/kml.c @@ -0,0 +1,313 @@ +/* + Support for Keyhole "kml" format. + + Copyright (C) 2005 Robert Lipe, robertlipe@usa.net + Updates by Andrew Kirmse, akirmse at google.com + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + + */ +#include "defs.h" +#include "xmlgeneric.h" + +static char *deficon = NULL; + +static waypoint *wpt_tmp; + +FILE *fd; +FILE *ofd; + +static +arglist_t kml_args[] = { + {"deficon", &deficon, "Default icon name", NULL, ARGTYPE_STRING }, + {0, 0, 0, 0, 0} +}; + +#define MYNAME "kml" + +#if NO_EXPAT +void +kml_rd_init(const char *fname) +{ + fatal(MYNAME ": This build excluded KML support because expat was not installed.\n"); +} + +void +kml_read(void) +{ +} +#else + +static xg_callback wpt_s, wpt_e; +static xg_callback wpt_name, wpt_desc, wpt_coord; + +static +xg_tag_mapping kml_map[] = { + { wpt_s, cb_start, "/Folder/Placemark" }, + { wpt_e, cb_end, "/Folder/Placemark" }, +// { wpt_name_s, cb_start, "/Folder/Placemark/name" }, + { wpt_name, cb_cdata, "/Folder/Placemark/name" }, + { wpt_desc, cb_cdata, "/Folder/Placemark/description" }, +// { wpt_type, cb_cdata, "/Folder/Placemark/type" }, +// { wpt_link_s, cb_start, "/Folder/Placemark/link" }, +// { wpt_link, cb_cdata, "/Folder/Placemark/link" }, + { wpt_coord, cb_cdata, "/Folder/Placemark/Point/coordinates" }, + { NULL, 0, NULL } +}; + +void wpt_s(const char *args, const char **unused) +{ + wpt_tmp = waypt_new(); +// wpt_tmp = xcalloc(sizeof(*wpt_tmp), 1); +} + +void wpt_e(const char *args, const char **unused) +{ + waypt_add(wpt_tmp); +} + +#if 0 +void wpt_name_s(const char *args, const char **attrv) +{ + const char **avp = &attrv[0]; + while (*avp) { + if (0 == strcmp(avp[0], "id")) { + wpt_tmp->shortname = xstrdup(avp[1]); + } + avp+=2; + } +} +#endif + +void wpt_name(const char *args, const char **unused) +{ + if (args) wpt_tmp->shortname = xstrdup(args); +} + +void wpt_desc(const char *args, const char **unused) +{ + if (args) wpt_tmp->description = xstrappend(wpt_tmp->description, args); +} + +void wpt_coord(const char *args, const char **attrv) +{ + sscanf(args, "%lf,%lf,%lf", &wpt_tmp->longitude, &wpt_tmp->latitude, &wpt_tmp->altitude); +} + +static +void +kml_rd_init(const char *fname) +{ + xml_init(fname, kml_map); +} + +static +void +kml_read(void) +{ + xml_read(); +} +#endif + +void +kml_rd_deinit(void) +{ + xml_deinit(); +} + +void +kml_wr_init(const char *fname) +{ + ofd = xfopen(fname, "w", MYNAME); +} + +void +kml_wr_deinit(void) +{ + fclose(ofd); +} + +static void kml_output_timestamp(const waypoint *waypointp) +{ + if (waypointp->creation_time) { + fprintf(ofd, "\t \n"); + fprintf(ofd, "\t "); + xml_write_time(ofd, waypointp->creation_time, "timePosition"); + fprintf(ofd, "\t \n"); + } +} + +/* + * WAYPOINTS + */ + +static void kml_waypt_pr(const waypoint *waypointp) +{ + fprintf(ofd, "\t\n"); + write_optional_xml_entity(ofd, "\t", "name", waypointp->description); + fprintf(ofd, "\t #waypoint\n"); + + // Description + if (waypointp->url) { + char * odesc = xml_entitize(waypointp->url); + fprintf(ofd, "\t "); + fputs("\n", ofd); + fputs(odesc, ofd); + xfree(odesc); + fprintf(ofd, "\n\t\n"); + } + + // Location + fprintf(ofd, "\t \n"); + fprintf(ofd, "\t\t%f,%f,%f\n", + waypointp->longitude, waypointp->latitude, + waypointp->altitude == unknown_alt ? 0.0 : waypointp->altitude); + fprintf(ofd, "\t \n"); + + // Timestamp + kml_output_timestamp(waypointp); + + fprintf(ofd, "\t\n"); +} + +/* + * TRACKPOINTS + */ + +static void kml_track_hdr(const route_head *header) +{ + fprintf(ofd, "\n"); + fprintf(ofd, " 1\n"); + write_optional_xml_entity(ofd, " ", "name", header->rte_name); + write_optional_xml_entity(ofd, " ", "desc", header->rte_desc); +} + +static void kml_track_disp(const waypoint *waypointp) +{ + fprintf(ofd, "\t\n"); + fprintf(ofd, "\t #track\n"); + fprintf(ofd, "\t \n"); + fprintf(ofd, "\t %f,%f,%f\n", + waypointp->longitude, waypointp->latitude, + waypointp->altitude == unknown_alt ? 0.0 : waypointp->altitude); + fprintf(ofd, "\t \n"); + + // Timestamp + kml_output_timestamp(waypointp); + + fprintf(ofd, "\t\n"); +} + +static void kml_track_tlr(const route_head *header) +{ + fprintf(ofd, "\n"); +} + +/* + * ROUTES + */ + +static void kml_route_hdr(const route_head *header) +{ + fprintf(ofd, "\n"); + fprintf(ofd, " 1\n"); + write_optional_xml_entity(ofd, " ", "name", header->rte_name); + write_optional_xml_entity(ofd, " ", "desc", header->rte_desc); +} + +static void kml_route_disp(const waypoint *waypointp) +{ + fprintf(ofd, "\t\n"); + fprintf(ofd, "\t #route\n"); + fprintf(ofd, "\t \n"); + fprintf(ofd, "\t %f,%f,%f\n", + waypointp->longitude, waypointp->latitude, + waypointp->altitude == unknown_alt ? 0.0 : waypointp->altitude); + fprintf(ofd, "\t \n"); + write_optional_xml_entity(ofd, "\t", "name", waypointp->description); + + // Timestamp + kml_output_timestamp(waypointp); + + fprintf(ofd, "\t\n"); +} + +static void kml_route_tlr(const route_head *header) +{ + fprintf(ofd, "\n"); +} + +static void kml_write_bitmap_style(const char *style, int bitmap, + int x, int y, int width, int height) +{ + fprintf(ofd, "\n"); +} + +void kml_write(void) +{ + fprintf(ofd, "\n"); + fprintf(ofd, "\n"); + // TODO(akirmse): Put in device name, maybe time? + fprintf(ofd, "GPS device\n"); + fprintf(ofd, "1\n"); + + // Style settings for bitmaps + kml_write_bitmap_style("track", 4, 128, 0, 32, 32); + kml_write_bitmap_style("waypoint", 4, 160, 0, 32, 32); + kml_write_bitmap_style("route", 4, 160, 0, 32, 32); + + fprintf(ofd, "\n"); + fprintf(ofd, "Waypoints\n"); + fprintf(ofd, "1\n"); + + waypt_disp_all(kml_waypt_pr); + + fprintf(ofd, "\n"); + + // Output trackpoints + fprintf(ofd, "\n"); + fprintf(ofd, "Tracks\n"); + fprintf(ofd, "1\n"); + track_disp_all(kml_track_hdr, kml_track_tlr, kml_track_disp); + fprintf(ofd, "\n"); + + // Output routes + fprintf(ofd, "\n"); + fprintf(ofd, "Routes\n"); + fprintf(ofd, "1\n"); + route_disp_all(kml_route_hdr, kml_route_tlr, kml_route_disp); + fprintf(ofd, "\n"); + + fprintf(ofd, "\n"); +} + +ff_vecs_t kml_vecs = { + ff_type_file, + FF_CAP_RW_WPT, /* Format can do RW_ALL */ + kml_rd_init, + kml_wr_init, + kml_rd_deinit, + kml_wr_deinit, + kml_read, + kml_write, + NULL, + kml_args +}; diff --git a/lowranceusr.c b/lowranceusr.c new file mode 100644 index 000000000..12b78e375 --- /dev/null +++ b/lowranceusr.c @@ -0,0 +1,389 @@ +/* + Access to Lowrance USR files. + Contributed to gpsbabel by Jason Rust (jrust at rustyparts.com) + + Copyright (C) 2005 Robert Lipe, robertlipe@usa.net + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA +*/ + + +#include "defs.h" +#include +#include /* for lat/lon conversion */ + +typedef struct lowranceusr_icon_mapping { + const long int value; + const char *icon; +} lowranceusr_icon_mapping_t; + +/* Taken from iFinder 1.8 */ +const lowranceusr_icon_mapping_t lowranceusr_icon_value_table[] = { + { 10000, "diamond 1" }, + { 10001, "diamond 2" }, + { 10002, "diamond 3" }, + { 10003, "x 1" }, + { 10004, "x 2" }, + { 10005, "x 3" }, + { 10006, "cross" }, + { 10007, "house" }, + { 10008, "car" }, + { 10009, "store" }, + { 10010, "gas station" }, + { 10011, "fork and spoon" }, + { 10012, "telephone" }, + { 10013, "airplane" }, + { 10014, "exit sign" }, + { 10015, "stop sign" }, + { 10016, "exclamation" }, + { 10017, "traffic light" }, + { 10018, "american flag" }, + { 10019, "person" }, + { 10020, "restrooms" }, + { 10021, "tree" }, + { 10022, "mountains" }, + { 10023, "campsite" }, + { 10024, "picnic table" }, + { 10025, "deer" }, + { 10026, "deer tracks" }, + { 10027, "turkey tracks" }, + { 10028, "tree stand" }, + { 10029, "bridge" }, + { 10030, "skull and crossbones" }, + { 10031, "fish" }, + { 10032, "two fish" }, + { 10033, "dive flag" }, + { 10034, "wreck" }, + { 10035, "anchor" }, + { 10036, "boat" }, + { 10037, "boat ramp" }, + { 10038, "flag buoy" }, + { 10039, "dam" }, + { 10040, "swimmer" }, + { 10041, "pier"}, + + { 10038, "Micro-Cache" }, /* icon for "flag buoy" */ + { 10030, "Virtual cache" }, /* icon for "skull and crossbones" */ + { 10032, "Multi-Cache" }, /* icon for "two fish" */ + { 10003, "Unknown Cache" }, /* icon for "x 1" */ + { 10018, "Locationless (Reverse) Cache" }, /* Icon for "american flag" */ + { 10007, "Post Office" }, /* Icon for "house" */ + { 10019, "Event Cache" }, /* Icon for "person" */ + { 10020, "Webcam Cache" }, /* Icon for "restrooms" */ + { -1, NULL } +}; + +static FILE *file_in; +static FILE *file_out; +static void *mkshort_handle; + +static unsigned short waypt_out_count; + +#define MYNAME "Lowrance USR" + +#define MAXUSRSTRINGSIZE 256 +#define SEMIMINOR 6356752.3142 +#define DEGREESTORADIANS 0.017453292 +#define SECSTO2000 946713599 + +static +size_t +my_fwrite4(int *ptr, FILE *stream) +{ + int i = le_read32(ptr); + return fwrite(&i, 4, 1, stream); +} + +static +size_t +my_fwrite2(short *ptr, FILE *stream) +{ + short i = le_read16(ptr); + return fwrite(&i, 2, 1, stream); +} + +const char * +lowranceusr_find_desc_from_icon_number(const int icon) +{ + const lowranceusr_icon_mapping_t *i; + + for (i = lowranceusr_icon_value_table; i->icon; i++) { + if (icon == i->value) { + return i->icon; + } + } + + return ""; +} + +long int +lowranceusr_find_icon_number_from_desc(const char *desc) +{ + const lowranceusr_icon_mapping_t *i; + long int def_icon = 10001; + + if (!desc) { + return def_icon; + } + + for (i = lowranceusr_icon_value_table; i->icon; i++) { + if (case_ignore_strcmp(desc,i->icon) == 0) { + return i->value; + } + } + + return def_icon; +} +static int +lowranceusr_fread(void *buff, size_t size, size_t members, FILE * fp) +{ + size_t br; + + br = fread(buff, size, members, fp); + + if (br != members) { + fatal(MYNAME ": requested to read %d bytes, read %d bytes.\n", members, br); + } + + return (br); +} + +static +arglist_t lowranceusr_args[] = { + {0, 0, 0, 0,0 } +}; + +static void +rd_init(const char *fname) +{ + file_in = xfopen(fname, "rb", MYNAME); +} + +static void +rd_deinit(void) +{ + fclose(file_in); +} + +static void +wr_init(const char *fname) +{ + file_out = xfopen(fname, "wb", MYNAME); + mkshort_handle = mkshort_new_handle(); + waypt_out_count = 0; +} + +static void +wr_deinit(void) +{ + fclose(file_out); + mkshort_del_handle(mkshort_handle); +} + +/** + * Latitude and longitude for USR coords are in the lowrance mercator meter + * format in WGS84. The below code converts them to degrees. + */ +static double +lon_mm_to_deg(double x) { + return x / (DEGREESTORADIANS * SEMIMINOR); +} + +static long +lon_deg_to_mm(double x) { + return (long)(x * SEMIMINOR * DEGREESTORADIANS); +} + +static double +lat_mm_to_deg(double x) { + return (2 * atan(exp(x / SEMIMINOR)) - M_PI / 2) / DEGREESTORADIANS; +} + +static long +lat_deg_to_mm(double x) { + return (long)(SEMIMINOR * log(tan((x * DEGREESTORADIANS + M_PI / 2) / 2))); +} + +static void +data_read(void) +{ + char buff[MAXUSRSTRINGSIZE + 1]; + short int NumWaypoints, MajorVersion, MinorVersion; + int i; + long int TextLen; + + lowranceusr_fread(&buff[0], 2, 1, file_in); + MajorVersion = le_read16(&buff[0]); + lowranceusr_fread(&buff[0], 2, 1, file_in); + MinorVersion = le_read16(&buff[0]); + + if (MajorVersion < 2) { + fatal(MYNAME ": input file is from an old version of the USR file and is not supported\n"); + } + + lowranceusr_fread(&buff[0], 2, 1, file_in); + NumWaypoints = le_read16(&buff[0]); + for (i = 0; i < NumWaypoints; i++) { + waypoint *wpt_tmp; + + wpt_tmp = waypt_new(); + + /* Object num */ + lowranceusr_fread(&buff[0], 2, 1, file_in); + lowranceusr_fread(&buff[0], 4, 1, file_in); + wpt_tmp->latitude = lat_mm_to_deg(le_read32(&buff[0])); + lowranceusr_fread(&buff[0], 4, 1, file_in); + wpt_tmp->longitude = lon_mm_to_deg(le_read32(&buff[0])); + lowranceusr_fread(&buff[0], 4, 1, file_in); + wpt_tmp->altitude = le_read32(&buff[0]); + + lowranceusr_fread(&buff[0], 4, 1, file_in); + TextLen = buff[0]; + lowranceusr_fread(&buff[0], TextLen, 1, file_in); + buff[TextLen] = '\0'; + wpt_tmp->shortname = xstrdup(buff); + + lowranceusr_fread(&buff[0], 4, 1, file_in); + TextLen = buff[0]; + if (TextLen) { + lowranceusr_fread(&buff[0], TextLen, 1, file_in); + buff[TextLen] = '\0'; + wpt_tmp->description = xstrdup(buff); + } + + lowranceusr_fread(&buff[0], 4, 1, file_in); + /* Time is number of seconds since Jan. 1, 2000 */ + wpt_tmp->creation_time = SECSTO2000 + le_read32(&buff[0]); + + /* Symbol ID */ + lowranceusr_fread(&buff[0], 4, 1, file_in); + wpt_tmp->icon_descr = lowranceusr_find_desc_from_icon_number(le_read32(&buff[0])); + + /* Waypoint Type (USER, TEMPORARY, POINT_OF_INTEREST) */ + lowranceusr_fread(&buff[0], 2, 1, file_in); + + waypt_add(wpt_tmp); + } +} + +static void +lowranceusr_waypt_pr(const waypoint *wpt) +{ + int TextLen, Lat, Lon, Time, SymbolId; + short int WayptType; + char *name; + char *comment; + int alt = wpt->altitude; + + /* our personal waypoint counter */ + my_fwrite2((short *) &waypt_out_count, file_out); + waypt_out_count++; + + Lat = lat_deg_to_mm(wpt->latitude); + my_fwrite4(&Lat, file_out); + Lon = lon_deg_to_mm(wpt->longitude); + my_fwrite4(&Lon, file_out); + my_fwrite4(&alt, file_out); + + /* Try and make sure we have a name */ + if ((! wpt->shortname) || global_opts.synthesize_shortnames) { + if (wpt->description && global_opts.synthesize_shortnames) { + name = mkshort_from_wpt(mkshort_handle, wpt); + } else if (wpt->shortname) { + name = xstrdup(wpt->shortname); + } else if (wpt->description) { + name = xstrdup(wpt->description); + } else { + name = xstrdup(""); + } + } else { + name = xstrdup(wpt->shortname); + } + + TextLen = strlen(name); + my_fwrite4(&TextLen, file_out); + fwrite(name, 1, TextLen, file_out); + xfree(name); + + /** + * Comments aren't used by the iFinder yet so they just take up space... + */ + if (0 && wpt->description && strcmp(wpt->description, wpt->shortname) != 0) { + comment = xstrdup(wpt->description); + TextLen = strlen(comment); + my_fwrite4(&TextLen, file_out); + fwrite(comment, 1, TextLen, file_out); + xfree(comment); + } else { + TextLen = 0; + my_fwrite4(&TextLen, file_out); + } + + if (wpt->creation_time > SECSTO2000) { + Time = wpt->creation_time - SECSTO2000; + } else { + Time = SECSTO2000 + 1; + } + my_fwrite4(&Time, file_out); + + if (get_cache_icon(wpt) && wpt->icon_descr && (strcmp(wpt->icon_descr, "Geocache Found") != 0)) { + SymbolId = lowranceusr_find_icon_number_from_desc(get_cache_icon(wpt)); + } else { + SymbolId = lowranceusr_find_icon_number_from_desc(wpt->icon_descr); + } + + my_fwrite4(&SymbolId, file_out); + + /* USER waypoint type */ + WayptType = 0; + my_fwrite2(&WayptType, file_out); +} + +static void +data_write(void) +{ + short int NumWaypoints, MajorVersion, MinorVersion, NumRoutes, NumTrails, NumIcons; + setshort_length(mkshort_handle, 15); + MajorVersion = 2; + MinorVersion = 0; + NumWaypoints = waypt_count(); + + my_fwrite2(&MajorVersion, file_out); + my_fwrite2(&MinorVersion, file_out); + my_fwrite2(&NumWaypoints, file_out); + waypt_disp_all(lowranceusr_waypt_pr); + + /* We don't support these yet... */ + NumRoutes = 0; + my_fwrite2(&NumRoutes, file_out); + NumIcons = 0; + my_fwrite2(&NumIcons, file_out); + NumTrails = 0; + my_fwrite2(&NumTrails, file_out); +} + + +ff_vecs_t lowranceusr_vecs = { + ff_type_file, + FF_CAP_RW_WPT, + rd_init, + wr_init, + rd_deinit, + wr_deinit, + data_read, + data_write, + NULL, + lowranceusr_args +}; diff --git a/macgpsbabel/Credits.rtf b/macgpsbabel/Credits.rtf index a133febb1..810310197 100644 --- a/macgpsbabel/Credits.rtf +++ b/macgpsbabel/Credits.rtf @@ -3,29 +3,19 @@ {\colortbl;\red255\green255\blue255;} \pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\ql\qnatural -\f0\b\fs24 \cf0 Acknowledgements. -\f1\b0 \ -\ - -\f0\b Gpsbabel +\f0\b\fs24 \cf0 Gpsbabel \f1\b0 is an open-source project created and administrated by \f0\b Robert Lipe \f1\b0 .\ \f0\b MacGPSBabel -\f1\b0 is a GUI front-end for gpsbabel. It was designed by +\f1\b0 is a GUI front-end for gpsbabel designed by \f0\b Jeremy Atherton \f1\b0 .\ \ -Thanks to the many people who have tested MacGPSBabel and given suggestions for improvement.\ -\ - -\f0\b Legal. -\f1\b0 \ +This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.\ \ -Gpsbabel and MacGPSBabel are free software; you can redistribute them and/or modify them under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.\ -\ -Gpsbabel and MacGPSBabel are distributed in the hope that they will be useful, but +This program is distributed in the hope that it will be useful, but \f0\b WITHOUT ANY WARRANTY \f1\b0 ; without even the implied warranty of \f0\b MERCHANTABILITY @@ -41,7 +31,6 @@ You should have received a copy of the GNU General Public License along with thi \f0\b Robert Lipe \f1\b0 \ \ -\ For questions or comments regarding MacGPSBabel please visit http://gpsbabel.souceforge.net/ and use the gpsbabel-misc email list. Alternatively you can contact Jeremy Atherton through the address posted at the sourceforge site.\ \ -If you would like to contribute your programming skills to either gpsbabel or MacGPSBabel please do. Join the gpsbabel-code email list and get involved.} \ No newline at end of file +Thanks to the many people who have tested MacGPSBabel and given suggestions for improvement. If you would like to contribute your programming skills to either gpsbabel or MacGPSBabel please do. Join the gpsbabel-code email list and get involved.} \ No newline at end of file diff --git a/macgpsbabel/English.lproj/MainMenu.nib/objects.nib b/macgpsbabel/English.lproj/MainMenu.nib/objects.nib index 92e08d284a77bdadf4f0ff7af0b236f7215d07e7..fb2a7b0dae32c2003f59772c8ce3bfacac539740 100644 GIT binary patch literal 22092 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 KU3irvo&Imsj|yG@ diff --git a/macgpsbabel/MacGPSBabel.applescript b/macgpsbabel/MacGPSBabel.applescript index 1aee120cc..76d6c1204 100644 --- a/macgpsbabel/MacGPSBabel.applescript +++ b/macgpsbabel/MacGPSBabel.applescript @@ -1,16 +1,33 @@ -- MacGPSBabel: MacGPSBabel.applescript -- File created by Jeremy Atherton on Sunday, September 28, 2003. --- Last modified by Jeremy Atherton on Tuesday, September 7, 2004. +-- Last modified by Jeremy Atherton on Sunday, January 16, 2005. + +-- MacGPSBabel is part of the gpsbabel project: + +-- Copyright (C) 2003 - 2005 Robert Lipe + +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 2 of the License, or +-- (at your option) any later version. + +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. + +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA --- MacGPSBabel is part of the gpsbabel project and is Copyright (c) 2004 Robert Lipe. -- see http://gpsbabel.sourceforge.net/ for more details -- PROPERTIES AND GLOBALS -- property fileList : {} property startIndex : 0 property startState : false -global theFiles, typeList, extList, aFile +global theFiles, inFormatList, outFormatList, inRWList, outRWList, inTypeList, outTypeList, extList, aFile -- EVENT HANDLERS -- @@ -23,22 +40,19 @@ on will finish launching theObject make new default entry at end of default entries of user defaults with properties {name:"gpsIN", contents:startState} make new default entry at end of default entries of user defaults with properties {name:"gpsOUT", contents:startState} make new default entry at end of default entries of user defaults with properties {name:"gpsReceiver", contents:startIndex} + make new default entry at end of default entries of user defaults with properties {name:"filterNSSelect", contents:startIndex} + make new default entry at end of default entries of user defaults with properties {name:"filterEWSelect", contents:startIndex} + make new default entry at end of default entries of user defaults with properties {name:"filterNDeg", contents:0} + make new default entry at end of default entries of user defaults with properties {name:"filterNMin", contents:0.0} + make new default entry at end of default entries of user defaults with properties {name:"filterWDeg", contents:0} + make new default entry at end of default entries of user defaults with properties {name:"filterWMin", contents:0.0} end will finish launching on awake from nib theObject log "awake from nib - " & name of theObject if theObject is window "MacGPSBabel" then - -- get supported file types from gpsbabel and use these to populate the file types popup lists - tell window "MacGPSBabel" - set popList to my getFormats() - repeat with i in popList - make new menu item at the end of menu items of menu of popup button "inPop" with properties {title:i, enabled:true} - make new menu item at the end of menu items of menu of popup button "outPop" with properties {title:i, enabled:true} - end repeat - end tell - - -- read current user defaults and set window controls as needed - my readSettings() + -- get supported file types from gpsbabel and use these to populate the file types popup list + my getFormats() -- deal with changes to MacGPSBabel window needed if any of the GPS check boxes are checked by default if state of button "GPSswitchIN" of window "MacGPSBabel" is equal to 1 then @@ -53,6 +67,7 @@ end awake from nib -- Deal with the opening and closing of windows on will open theObject + log "will open - " & name of theObject -- Main Window if theObject is window "MacGPSBabel" then @@ -71,6 +86,7 @@ on will open theObject repeat with i in popList make new menu item at the end of menu items of menu of popup button "serialPop" of window "SelectGPS" with properties {title:i, enabled:true} end repeat + make new menu item at the end of menu items of menu of popup button "serialPop" of window "SelectGPS" with properties {title:"Garmin USB", enabled:true} -- read user defaults for this window tell user defaults @@ -102,6 +118,8 @@ end will close -- handler for the File>Open menu item on choose menu item theObject log "choose menu item - " & name of theObject + + -- mainMenu File>Open if name of theObject is "open" then if visible of window "MacGPSBabel" is true then if contents of text field "inputFile" of window "MacGPSBabel" is equal to "" then @@ -128,6 +146,10 @@ on choose menu item theObject my addFile() end if end if + + if name of theObject is "modePop" then + my getFormats() + end if end choose menu item -- HANDLERS FOR BUTTON CLICKS @@ -245,6 +267,8 @@ on clicked theObject set editable of text field "wDeg" of window "filterWindow" to true set enabled of text field "wMin" of window "filterWindow" to true set editable of text field "wMin" of window "filterWindow" to true + set enabled of button "makeHomeButton" of window "filterWindow" to true + set enabled of button "useHomeButton" of window "filterWindow" to true tell window "filterWindow" set first responder to text field "dist2" end tell @@ -262,6 +286,61 @@ on clicked theObject set editable of text field "wDeg" of window "filterWindow" to false set enabled of text field "wMin" of window "filterWindow" to false set editable of text field "wMin" of window "filterWindow" to false + set enabled of button "makeHomeButton" of window "filterWindow" to false + set enabled of button "useHomeButton" of window "filterWindow" to false + end if + end if + + -- Filter Window - Make Home Button + if theObject is button "makeHomeButton" of window "filterWindow" then + set newNSIndex to contents of popup button "nsSelect" of window "filterWindow" + set newEWIndex to contents of popup button "ewSelect" of window "filterWindow" + set newNDeg to contents of text field "nDeg" of window "filterWindow" + set newNMin to contents of text field "nMin" of window "filterWindow" + set newWDeg to contents of text field "wDeg" of window "filterWindow" + set newWMin to contents of text field "wMin" of window "filterWindow" + tell user defaults + set contents of default entry "filterNSSelect" to newNSIndex as integer + set contents of default entry "filterEWSelect" to newEWIndex as integer + set contents of default entry "filterNDeg" to newNDeg as integer + set contents of default entry "filterNMin" to newNMin as number + set contents of default entry "filterWDeg" to newWDeg as integer + set contents of default entry "filterWMin" to newWMin as number + end tell + end if + + -- Filter Window - Use Home Button + if theObject is button "useHomeButton" of window "filterWindow" then + tell user defaults + set homeNSSelectIndex to contents of default entry "filterNSSelect" as integer + set homeEWSelectIndex to contents of default entry "filterEWSelect" as integer + set homeNDeg to contents of default entry "filterNDeg" as integer + set homeWDeg to contents of default entry "filterWDeg" as integer + set homeNMin to contents of default entry "filterNMin" as number + set homeWMin to contents of default entry "filterWMin" as number + end tell + set contents of popup button "nsSelect" of window "filterWindow" to homeNSSelectIndex + set contents of popup button "ewSelect" of window "filterWindow" to homeEWSelectIndex + set contents of text field "nDeg" of window "filterWindow" to homeNDeg + set contents of text field "wDeg" of window "filterWindow" to homeWDeg + set contents of text field "nMin" of window "filterWindow" to homeNMin + set contents of text field "wMin" of window "filterWindow" to homeWMin + end if + + -- Filter Window - Duplicate filter check boxes + if theObject is the button "locationFilter" of window "filterWindow" then + if state of button "locationFilter" of window "filterWindow" is equal to 1 then + set enabled of button "allSwitch" of window "filterWindow" to 1 + else if state of button "shortFilter" of window "filterWindow" is equal to 0 then + set enabled of button "allSwitch" of window "filterWindow" to 0 + end if + end if + + if theObject is the button "shortFilter" of window "filterWindow" then + if state of button "shortFilter" of window "filterWindow" is equal to 1 then + set enabled of button "allSwitch" of window "filterWindow" to 1 + else if state of button "locationFilter" of window "filterWindow" is equal to 0 then + set enabled of button "allSwitch" of window "filterWindow" to 0 end if end if @@ -278,12 +357,14 @@ on clicked theObject set enabled of text field "arcDist" of window "filterWindow" to true set editable of text field "arcDist" of window "filterWindow" to true set enabled of popup button "arcUnits" of window "filterWindow" to true + set enabled of button "arcPointsSwitch" of window "filterWindow" to true else set contents of text field "arcFile" of window "filterWindow" to "" set contents of text field "arcDist" of window "filterWindow" to "" set enabled of text field "arcDist" of window "filterWindow" to false set editable of text field "arcDist" of window "filterWindow" to false set enabled of popup button "arcUnits" of window "filterWindow" to false + set enabled of button "arcPointsSwitch" of window "filterWindow" to false end if end if @@ -369,8 +450,6 @@ on sendFile(fileList) return 0 else if state of button "GPSswitchOUT" of window "MacGPSBabel" = 1 then set visible of window "SelectGPS" to true - set state of button "trackSwitch" of window "SelectGPS" to 0 - set enabled of button "trackSwitch" of window "SelectGPS" to false return 0 else if the title of current menu item of popup button "inPop" of window "MacGPSBabel" = "Select Input File Type" then display dialog "Please select an input file type" buttons {"OK"} default button 1 @@ -393,18 +472,27 @@ on convertFile(fileList) set filterText to "" end if + -- waypoint, routes or tracks + if the title of popup button "modePop" of window "MacGPSBabel" is equal to "Tracks" then + set trackText to " -t" + else if the title of popup button "modePop" of window "MacGPSBabel" is equal to "Routes" then + set trackText to " -r" + else + set trackText to "" + end if + -- create string for input files set fileText to "" repeat with theItem in fileList set currentInIndex to item 2 of theItem - set inType to item (currentInIndex) of typeList + set inType to item (currentInIndex) of inTypeList set inputFile to quoted form of item 1 of theItem set fileText to fileText & " -i " & inType & " -f " & inputFile end repeat -- create strings for output file set currentOutIndex to contents of popup button "outPop" of window "MacGPSBabel" - set outType to item (currentOutIndex) of typeList + set outType to item (currentOutIndex) of outTypeList if visible of window "filterWindow" is true then if state of button "smartSwitch" of window "filterWindow" is equal to 1 then set smartSwitch to " -s" @@ -443,7 +531,7 @@ on convertFile(fileList) end if -- do the script set thePath to POSIX path of (path to me) as string - set theConvertScript to (quoted form of thePath & "Contents/Resources/gpsbabel" & smartSwitch & fileText & " " & filterText & "-o " & outType & " -F " & quoted form of outputFile) as string + set theConvertScript to (quoted form of thePath & "Contents/Resources/gpsbabel" & smartSwitch & trackText & fileText & " " & filterText & "-o " & outType & " -F " & quoted form of outputFile) as string if (my runBabel(theConvertScript)) then display dialog "File conversion is complete" buttons {"OK"} default button 1 else @@ -459,7 +547,6 @@ on GPSSend() display dialog "Please select an output file type" buttons {"OK"} default button 1 else set visible of window "SelectGPS" to true - set enabled of button "trackSwitch" of window "selectGPS" to true end if end GPSSend -- deal with uploading files to GPS receiver @@ -471,45 +558,66 @@ on uploadFile(fileList) set filterText to "" end if + -- waypoint, routes or tracks + if the title of popup button "modePop" of window "MacGPSBabel" is equal to "Tracks" then + set trackText to " -t" + else if the title of popup button "modePop" of window "MacGPSBabel" is equal to "Routes" then + set trackText to " -r" + else + set trackText to "" + end if + -- create string for input files set fileText to "" repeat with theItem in fileList set currentInIndex to item 2 of theItem - set inType to item (currentInIndex) of typeList + set inType to item (currentInIndex) of inTypeList set inputFile to quoted form of item 1 of theItem set fileText to fileText & " -i " & inType & " -f " & inputFile end repeat -- create string for GPS unit if the title of popup button "gpsPop" of window "selectGPS" is equal to "Garmin" then - set gpsText to " garmin " + set gpsRText to "garmin" else - set gpsText to " magellan " + set gpsRText to "magellan" end if if visible of window "filterWindow" is true then if state of button "smartSwitch" of window "filterWindow" is equal to 1 then set smartSwitch to " -s" if contents of text field "smartLen" of window "filterWindow" is not equal to "" then - set gpsText to gpsText & ",snlen=" & ((contents of text field "smartLen" of window "filterWindow") as integer) & " " + set gpsText to gpsRText & ",snlen=" & ((contents of text field "smartLen" of window "filterWindow") as integer) + else + set gpsText to gpsRText end if else set smartSwitch to "" + set gpsText to gpsRText end if else set smartSwitch to "" + set gpsText to gpsRText + end if + + -- get the port + if the the title of popup button "serialPop" of window "selectGPS" is equal to "Garmin USB" then + set serialText to "usb:" + else + set serialText to quoted form of ("/dev/cu." & (the title of popup button "serialPop" of window "selectGPS")) end if -- run the script set thePath to POSIX path of (path to me) as string set visible of window "SelectGPS" to false set visible of window "MacGPSBabel" to true - set serialText to "-F /dev/cu." & (the title of popup button "serialPop" of window "selectGPS") - set theConvertScript to (quoted form of thePath & "Contents/Resources/gpsbabel" & smartSwitch & fileText & " " & filterText & "-o " & gpsText & serialText) + + set theConvertScript to (quoted form of thePath & "Contents/Resources/gpsbabel" & smartSwitch & trackText & fileText & " " & filterText & "-o " & gpsText & " -F " & serialText) if (my runBabel(theConvertScript)) then - display dialog "Upload to" & gpsText & "GPS receiver is complete" buttons {"OK"} default button 1 + display dialog "Upload to " & gpsRText & " GPS receiver is complete" buttons {"OK"} default button 1 else - display dialog "Sorry, upload to" & gpsText & "GPS receiver failed" buttons {"OK"} default button 1 + display dialog "Sorry, upload to " & gpsRText & " GPS receiver failed" buttons {"OK"} default button 1 end if + my clearFiles() end uploadFile -- deal with downloading files from GPS receiver on downloadFile() @@ -519,9 +627,14 @@ on downloadFile() else set filterText to "" end if - if state of button "trackSwitch" of window "selectGPS" is equal to 1 then + + -- waypoint, routes or tracks + if the title of popup button "modePop" of window "MacGPSBabel" is equal to "Tracks" then set trackText to " -t" set outName to "Tracks." + else if the title of popup button "modePop" of window "MacGPSBabel" is equal to "Routes" then + set trackText to " -r" + set outName to "Routes." else set trackText to "" end if @@ -534,7 +647,7 @@ on downloadFile() end tell set currentOutIndex to contents of popup button "outPop" of window "MacGPSBabel" - set outType to item (currentOutIndex) of typeList + set outType to item (currentOutIndex) of outTypeList if visible of window "filterWindow" is true then if state of button "smartSwitch" of window "filterWindow" is equal to 1 then set smartSwitch to " -s" @@ -557,10 +670,15 @@ on downloadFile() else set gpsText to " magellan " end if - set serialText to "/dev/cu." & (the title of popup button "serialPop" of window "selectGPS") + -- get the port + if the the title of popup button "serialPop" of window "selectGPS" is equal to "Garmin USB" then + set serialText to "usb:" + else + set serialText to quoted form of ("/dev/cu." & (the title of popup button "serialPop" of window "selectGPS")) + end if set visible of window "SelectGPS" to false set visible of window "MacGPSBabel" to true - set theConvertScript to (quoted form of thePath & "Contents/Resources/gpsbabel" & smartSwitch & trackText & " -i" & gpsText & "-f " & serialText & " " & filterText & " -o " & outType & " -F " & quoted form of outputFile) + set theConvertScript to (quoted form of thePath & "Contents/Resources/gpsbabel" & smartSwitch & trackText & " -i" & gpsText & "-f " & serialText & filterText & " -o " & outType & " -F " & quoted form of outputFile) if (my runBabel(theConvertScript)) then display dialog "Download from" & gpsText & "GPS receiver is complete" buttons {"OK"} default button 1 else @@ -569,6 +687,7 @@ on downloadFile() else set outputFile to "" end if + my clearFiles() end downloadFile -- Send the call to gpsbabel @@ -579,10 +698,12 @@ on runBabel(theConvertScript) try set scriptOut to do shell script theConvertScript as string set babelHappy to true + set convertYN to "ran successfully" log "Success! gpsbabel returned: " & scriptOut on error set scriptOut to "gpsbabel encountered an error" set babelHappy to false + set convertYN to "failed" log "Error! gpsbabel returned: " & scriptOut end try feedbackBusy(false) @@ -672,7 +793,11 @@ on applyFilters() set aUnit to "K" end if set arcDistance to (contents of text field "arcDist" of window "filterWindow") & aUnit - set arcText to "-x arc,file=\"" & (contents of text field "arcFile" of window "filterWindow") & "\",distance=" & arcDistance & " " + set arcText to "-x arc,file='" & (contents of text field "arcFile" of window "filterWindow") & "',distance=" & arcDistance + if the state of button "arcPointsSwitch" of window "filterWindow" is equal to 1 then + set arcText to arcText & ",points" + end if + set arcText to arcText & " " else display dialog "Please input a distance for the arc filter" buttons ["OK"] default button 1 set arcText to "" @@ -682,7 +807,7 @@ on applyFilters() set arcText to "" end if if state of button "polySwitch" of window "filterWindow" is equal to 1 then - set polyText to "-x polygon,file=\"" & (contents of text field "arcFile" of window "filterWindow") & "\" " + set polyText to "-x polygon,file='" & (contents of text field "polyFile" of window "filterWindow") & "'" else set polyText to "" end if @@ -743,15 +868,13 @@ on clearFiles() -- reset controls to user defaults -- read current user defaults and set window controls as needed - my readSettings() + if the title of popup button "modePop" of window "MacGPSBabel" is equal to "Waypoints" then + my readSettings() + end if -- deal with changes to MacGPSBabel window needed if any of the GPS check boxes are checked by default - if state of button "GPSswitchIN" of window "MacGPSBabel" is equal to 1 then - my gpsIN() - end if - if state of button "GPSswitchOUT" of window "MacGPSBabel" is equal to 1 then - my gpsOUT() - end if + my gpsIN() + my gpsOUT() end clearFiles @@ -763,8 +886,6 @@ on readSettings() set defaultgpsIN to contents of default entry "gpsIN" as boolean set defaultgpsOUT to contents of default entry "gpsOUT" as boolean end tell - -- call method "setObjectValue:" of object (popup button "inPop" of window "MacGPSBabel") with parameter defaultInputIndex - -- call method "synchronizeTitleAndSelectedItem" of object (popup button "inPop" of window "MacGPSBabel") set contents of popup button "inPop" of window "MacGPSBabel" to defaultInputIndex set contents of popup button "outPop" of window "MacGPSBabel" to defaultOutputIndex set state of button "GPSswitchIN" of window "MacGPSBabel" to defaultgpsIN @@ -816,24 +937,79 @@ on getSerial() return myList end getSerial --- handler (called at startup) to check with GPS Babel which file formats it can handle. Return the result as a list +-- handler (called at startup) to check with GPS Babel which file formats it can handle. +-- Populates global lists with file types and capabilities on getFormats() - set myList to {} - set typeList to {} + set inFormatList to {} + set outFormatList to {} + set inTypeList to {} + set outTypeList to {} set extList to {} set thePath to POSIX path of (path to me) as string - set scriptOut to (do shell script quoted form of thePath & "Contents/Resources/gpsbabel -^1") as string + set scriptOut to (do shell script quoted form of thePath & "Contents/Resources/gpsbabel -^2") as string set theCount to count of paragraphs in scriptOut set defaultDelimiters to AppleScript's text item delimiters set AppleScript's text item delimiters to tab repeat with i from 1 to theCount set theLine to paragraph i of scriptOut if (first text item of theLine) is equal to "file" then - set the end of typeList to the second text item of theLine - set the end of extList to the third text item of theLine - set the end of myList to the last text item of theLine + if the title of popup button "modePop" of window "MacGPSBabel" is equal to "Waypoints" then + if the first character of the second text item of theLine is equal to "r" then + set the end of inTypeList to the third text item of theLine + set the end of inFormatList to the last text item of theLine + end if + if the second character of the second text item of theLine is equal to "w" then + set the end of extList to the 4th text item of theLine + set the end of outTypeList to the third text item of theLine + set the end of outFormatList to the last text item of theLine + end if + end if + if the title of popup button "modePop" of window "MacGPSBabel" is equal to "Tracks" then + if the third character of the second text item of theLine is equal to "r" then + set the end of inTypeList to the third text item of theLine + set the end of inFormatList to the last text item of theLine + end if + if the 4th character of the second text item of theLine is equal to "w" then + set the end of extList to the 4th text item of theLine + set the end of outTypeList to the third text item of theLine + set the end of outFormatList to the last text item of theLine + end if + end if + if the title of popup button "modePop" of window "MacGPSBabel" is equal to "Routes" then + if the 5th character of the second text item of theLine is equal to "r" then + set the end of inTypeList to the third text item of theLine + set the end of inFormatList to the last text item of theLine + end if + if the 6th character of the second text item of theLine is equal to "w" then + set the end of extList to the 4th text item of theLine + set the end of outTypeList to the third text item of theLine + set the end of outFormatList to the last text item of theLine + end if + end if end if end repeat set AppleScript's text item delimiters to defaultDelimiters - return myList + + -- set current menu item of popup button "inPop" of window "MacGPSBabel" to menu item 1 of menu of popup button "inPop" of window "MacGPSBabel" + -- set current menu item of popup button "outPop" of window "MacGPSBabel" to menu item 1 of menu of popup button "outPop" of window "MacGPSBabel" + + tell window "MacGPSBabel" + if (count of menu items of popup button "inPop") is greater than 0 then + delete every menu item of menu of popup button "inPop" + make new menu item at the end of menu items of menu of popup button "inPop" with properties {title:"Select Input File Type", enabled:true} + delete every menu item of menu of popup button "outPop" + make new menu item at the end of menu items of menu of popup button "outPop" with properties {title:"Select Output File Type", enabled:true} + end if + repeat with i in inFormatList + make new menu item at the end of menu items of menu of popup button "inPop" with properties {title:i, enabled:true} + end repeat + repeat with i in outFormatList + make new menu item at the end of menu items of menu of popup button "outPop" with properties {title:i, enabled:true} + end repeat + end tell + + if the title of popup button "modePop" of window "MacGPSBabel" is equal to "Waypoints" then + my readSettings() + end if + end getFormats \ No newline at end of file diff --git a/macgpsbabel/MacGPSBabel.pbproj/project.pbxproj b/macgpsbabel/MacGPSBabel.pbproj/project.pbxproj index c2d2aad14..2d326e9a5 100644 --- a/macgpsbabel/MacGPSBabel.pbproj/project.pbxproj +++ b/macgpsbabel/MacGPSBabel.pbproj/project.pbxproj @@ -193,7 +193,7 @@ 29B97319FDCFA39411CA2CEA = { isa = PBXFileReference; lastKnownFileType = wrapper.nib; - path = MainMenu.nib; + path = English.lproj/MainMenu.nib; refType = 4; sourceTree = ""; }; @@ -452,7 +452,7 @@ F514A08D05A6164F01A80064 = { isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; - path = gpsbabel; + path = ../gpsbabel; refType = 4; sourceTree = ""; }; diff --git a/magellan.h b/magellan.h index f7a023b16..062742634 100644 --- a/magellan.h +++ b/magellan.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002 Robert Lipe, robertlipe@usa.net + Copyright (C) 2002-2005 Robert Lipe, robertlipe@usa.net This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -47,5 +47,8 @@ typedef struct icon_mapping { const char * mag_find_descr_from_token(const char *token); const char * mag_find_token_from_descr(const char *icon); +unsigned int mag_checksum(const char *const buf); +char * m330_cleanse(char *istring); + waypoint * mag_trkparse(char *trkmsg); void mag_rteparse(char *rtemsg); diff --git a/maggeo.c b/maggeo.c new file mode 100644 index 000000000..3bf237cc1 --- /dev/null +++ b/maggeo.c @@ -0,0 +1,239 @@ +/* + Magellan ".gs" files as they appear on USB of Explorist 400,500,600. + + Copyright (C) 2005, robertlipe@usa.net + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + + */ + +#include +#include "defs.h" +#include "xmlgeneric.h" +#include "magellan.h" + +#define MYNAME "maggeo" + +static FILE *maggeofile_in; +static FILE *maggeofile_out; +static void *desc_handle = NULL; + +static void +maggeo_writemsg(const char * const buf) +{ + unsigned int osum = mag_checksum(buf); + fprintf(maggeofile_out, "$%s*%02X\r\n",buf, osum); +} + +static void +maggeo_rd_init(const char *fname) +{ + maggeofile_in = xfopen(fname, "rb", MYNAME); +} + +static void +maggeo_rd_deinit(void) +{ + fclose(maggeofile_in); +} + +static void +maggeo_wr_init(const char *fname) +{ + maggeofile_out = xfopen(fname, "wb", MYNAME); + desc_handle = mkshort_new_handle(); + setshort_length(desc_handle, 20); + setshort_badchars(desc_handle, "\"$,"); +} + +static void +maggeo_wr_deinit(void) +{ + maggeo_writemsg("PMGNCMD,END"); + fclose(maggeofile_out); +} + +static void +maggeo_read(void) +{ + fatal("Not implemented yet."); +} + +/* + * Note: returns allocated buffer that must be freed by caller. + */ +static +char * +maggeo_fmtdate(time_t t) +{ + #define SZ 16 + + char *cbuf = xmalloc(SZ); + struct tm *tm = NULL; + int date; + tm = gmtime(&t); + + if ( t && tm ) { + date = tm->tm_mday * 100000 + (1+tm->tm_mon) * 1000 + + tm->tm_year; + snprintf(cbuf, SZ, "%07d", date); + } else { + cbuf[0] = '\0'; + } + return cbuf; +} + +/* + * Append an optional UTF string to buf, prepending a comma, + * cleansing it of NMEA-isms and decomposing to ASCII as we go. + */ +static +append(char *buf, const char *str) +{ + char *cleansed1, *cleansed2; + + strcat(buf, ","); + + if (!str) { + return; + } + + cleansed1 = str_utf8_to_ascii(str); + cleansed2 = m330_cleanse(cleansed1); + + strcat(buf, cleansed2); + + xfree(cleansed1); + xfree(cleansed2); + +} + +static void +maggeo_waypt_pr(const waypoint *waypointp) +{ + char obuf[4096]; + char dtbuf[10]; + double ilon, ilat; + double lon, lat; + int lon_deg, lat_deg; + char *shortname; + char *cname = NULL; + char *ctype = NULL; + char *placer = NULL; + char *lfounddate = NULL; + char *placeddate = NULL; + + ilat = waypointp->latitude; + ilon = waypointp->longitude; + shortname = waypointp->shortname; + + lon = fabs(ilon); + lat = fabs(ilat); + + lon_deg = lon; + lat_deg = lat; + + lon = (lon - lon_deg) * 60.0; + lat = (lat - lat_deg) * 60.0; + + lon = (lon_deg * 100.0 + lon); + lat = (lat_deg * 100.0 + lat); + + ctype = gs_get_cachetype(waypointp->gc_data.type); + placeddate = maggeo_fmtdate(waypointp->creation_time); + lfounddate = maggeo_fmtdate(waypointp->gc_data.last_found); + cname = mkshort(desc_handle, waypointp->notes ? waypointp->notes : waypointp->shortname); + placer = waypointp->gc_data.placer; + + /* + * As of this writing on 05/04, the firmware in the units will + * let you write fields of just about any width, but appears to + * only use the following: + * shortname - 8 chars + * cname - 20 chars (scrolls in some places, not others) + * placer - display limited by width + * hint - 50 chars + * cache type - appears to be parsed by f/w for icon matching. + * + * + */ + snprintf(obuf, sizeof(obuf), + "PMGNGEO,%4.3f,%c,%08.3f,%c,%04.0f,F", + lat, ilat < 0 ? 'S' : 'N', + lon, ilon < 0 ? 'W' : 'E', + waypointp->altitude == unknown_alt ? + 0 : waypointp->altitude); + append(obuf, shortname); + append(obuf, cname); + append(obuf, placer); + append(obuf, waypointp->gc_data.hint); + append(obuf, ctype); + append(obuf, placeddate); + append(obuf, lfounddate); + + if (waypointp->gc_data.diff/10.0) + sprintf(obuf + strlen(obuf), ",%3.1f", + waypointp->gc_data.diff/10.0); + else + strcat(obuf, ","); + + if (waypointp->gc_data.terr/10.0) + sprintf(obuf + strlen(obuf), ",%3.1f", + waypointp->gc_data.terr/10.0); + else + strcat(obuf, ","); + + if (lfounddate) xfree(lfounddate); + if (placeddate) xfree(placeddate); + + maggeo_writemsg(obuf); + +} + +static void +maggeo_write(void) +{ + waypt_disp_all(maggeo_waypt_pr); +} + +static +char * +strconsume(char *instr, int *eaten) +{ + const char *origstr = instr; + char *s = instr; + char *e = instr; + int ct; + + while (e && *e && *e != ',') + *e++; + + *eaten = e - s; + + return (xstrndup(instr, e-s)); + +} + + +ff_vecs_t maggeo_vecs = { + ff_type_file, + FF_CAP_RW_WPT, + maggeo_rd_init, + maggeo_wr_init, + maggeo_rd_deinit, + maggeo_wr_deinit, + maggeo_read, + maggeo_write, +}; diff --git a/magnav.c b/magnav.c index 392974e40..8e9370dc9 100644 --- a/magnav.c +++ b/magnav.c @@ -106,7 +106,7 @@ data_read(void) struct tm tm; memset (&tm, sizeof(tm), 0); - wpt_tmp = xcalloc(sizeof(*wpt_tmp),1); + wpt_tmp = waypt_new(); rec = (struct record *) pdb_rec->data; wpt_tmp->altitude = be_read32(&rec->elevation); @@ -145,7 +145,7 @@ my_writewpt(const waypoint *wpt) char *vdata; time_t tm_t; const char *sn = global_opts.synthesize_shortnames ? - mkshort(mkshort_handle, wpt->description) : + mkshort_from_wpt(mkshort_handle, wpt) : wpt->shortname; rec = xcalloc(sizeof(*rec)+56,1); @@ -179,7 +179,7 @@ my_writewpt(const waypoint *wpt) be_write32(&rec->longitude, si_round(wpt->longitude * 100000.0)); be_write32(&rec->latitude, si_round(wpt->latitude * 100000.0)); - be_write32(&rec->elevation, wpt->altitude); + be_write32(&rec->elevation, (unsigned int) (wpt->altitude)); rec->plot = 0; rec->unknown3 = 'a'; @@ -205,7 +205,7 @@ my_writewpt(const waypoint *wpt) vdata[1] = '\0'; vdata += 2; - opdb_rec = new_Record (0, 0, ct++, vdata-(char *)rec, (const ubyte *)rec); + opdb_rec = new_Record (0, 0, ct++, (uword) (vdata-(char *)rec), (const ubyte *)rec); if (opdb_rec == NULL) { fatal(MYNAME ": libpdb couldn't create record\n"); @@ -263,6 +263,7 @@ data_write(void) ff_vecs_t magnav_vec = { ff_type_file, + FF_CAP_RW_WPT, rd_init, wr_init, rd_deinit, diff --git a/magproto.c b/magproto.c index 87424e204..48151b532 100644 --- a/magproto.c +++ b/magproto.c @@ -1,7 +1,7 @@ /* Communicate Thales/Magellan serial protocol. - Copyright (C) 2002, 2003, 2004 Robert Lipe, robertlipe@usa.net + Copyright (C) 2002, 2003, 2004, 2005 Robert Lipe, robertlipe@usa.net This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -26,7 +26,10 @@ #include "magellan.h" int bitrate = 4800; +int wptcmtcnt; +int wptcmtcnt_max; #define MYNAME "MAGPROTO" +#define MAXCMTCT 200 #define debug_serial (global_opts.debug_level > 1) @@ -38,10 +41,12 @@ static void mag_handoff(void); static void *mkshort_handle = NULL; static char *deficon = NULL; static char *bs = NULL; +static char *cmts = NULL; static char *noack = NULL; static char *nukewpt = NULL; static int route_out_count; static int waypoint_read_count; +static int wpt_len = 8; typedef enum { mrs_handoff = 0, @@ -171,7 +176,9 @@ pid_to_model_t pid_to_model[] = { mm_meridian, 35, "ProMark 2" }, { mm_sportrak, 36, "SporTrak Map/Pro" }, { mm_sportrak, 37, "SporTrak" }, + { mm_meridian, 38, "FX324 Plotter" }, { mm_meridian, 39, "Meridian Color" }, + { mm_meridian, 40, "FX324C Plotter" }, { mm_sportrak, 41, "Sportrak Color" }, { mm_sportrak, 42, "Sportrak Marine" }, { mm_meridian, 43, "Meridian Marine" }, @@ -207,7 +214,7 @@ m315_cleanse(char *istring) /* * Do same for 330, Meridian, and SportTrak. */ -static char * +char * m330_cleanse(char *istring) { static char m330_valid_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ " @@ -229,7 +236,7 @@ m330_cleanse(char *istring) * Given a protocol message, compute the checksum as needed by * the Magellan protocol. */ -static unsigned int +unsigned int mag_checksum(const char * const buf) { int csum = 0; @@ -359,7 +366,7 @@ mag_verparse(char *ibuf) case mm_meridian: case mm_sportrak: icon_mapping = map330_icon_table; - setshort_length(mkshort_handle, 8); + setshort_length(mkshort_handle, wpt_len); setshort_mustupper(mkshort_handle, 0); mag_cleanse = m330_cleanse; break; @@ -611,7 +618,7 @@ termwrite(char *obuf, int size) return; } WriteFile (comport, obuf, size, &len, NULL); - if (len != size) { + if ((int) len != size) { fatal(MYNAME ":. Wrote %d of %d bytes.\n", len, size); } } @@ -711,6 +718,8 @@ static arglist_t mag_sargs[] = { {"baud", &bs, "Numeric value of bitrate (baud=4800)", NULL, ARGTYPE_INT }, + {"maxcmts", &cmts, "Max number of comments to write (maxcmts=200)", + NULL, ARGTYPE_INT }, {"noack", &noack, "Suppress use of handshaking in name of speed", NULL, ARGTYPE_BOOL}, {"deficon", &deficon, "Default icon name", NULL, ARGTYPE_STRING }, @@ -786,8 +795,18 @@ mag_rd_init(const char *portname) } static void -mag_wr_init(const char *portname) +mag_wr_init_common(const char *portname) { + if (bs) { + bitrate=atoi(bs); + } + + if (cmts) { + wptcmtcnt_max = atoi(cmts); + } else { + wptcmtcnt_max = MAXCMTCT ; + } + #if __WIN32__ if (!terminit(portname, 1)) { is_file = 1; @@ -823,6 +842,24 @@ mag_wr_init(const char *portname) QUEUE_INIT(&rte_wpt_tmp); } +/* + * Entry point for extended (explorist) points. + */ +static void +magX_wr_init(const char *portname) +{ + wpt_len = 20; + mag_wr_init_common(portname); + setshort_length(mkshort_handle, wpt_len); +} + +static void +mag_wr_init(const char *portname) +{ + wpt_len = 8; + mag_wr_init_common(portname); +} + static void mag_deinit(void) { @@ -1150,7 +1187,7 @@ mag_waypt_pr(const waypoint *waypointp) const char *icon_token=NULL; char *owpt; char *odesc; - char *isrc; + char *isrc = NULL; ilat = waypointp->latitude; ilon = waypointp->longitude; @@ -1179,11 +1216,12 @@ mag_waypt_pr(const waypoint *waypointp) isrc = waypointp->notes ? waypointp->notes : waypointp->description; owpt = global_opts.synthesize_shortnames ? - mkshort(mkshort_handle, isrc) : waypointp->shortname; + mkshort_from_wpt(mkshort_handle, waypointp) : waypointp->shortname; odesc = isrc ? isrc : ""; owpt = mag_cleanse(owpt); - if (waypointp->gc_data.diff && waypointp->gc_data.terr) { + if (!global_opts.no_smart_icons && + waypointp->gc_data.diff && waypointp->gc_data.terr) { sprintf(ofmtdesc, "%d/%d %s", waypointp->gc_data.diff, waypointp->gc_data.terr, odesc); odesc = mag_cleanse(ofmtdesc); @@ -1191,11 +1229,20 @@ mag_waypt_pr(const waypoint *waypointp) odesc = mag_cleanse(odesc); } - sprintf(obuf, "PMGNWPL,%4.3f,%c,%09.3f,%c,%07.lf,M,%-.8s,%-.30s,%s", + /* + * For the benefit of DirectRoute (which uses waypoint comments + * to deliver turn-by-turn popups for street routing) allow a + * cap on the comments delivered so we leave space for it to route. + */ + if (odesc && /* !is_file && */ (wptcmtcnt++ >= wptcmtcnt_max)) + odesc[0] = 0; + + sprintf(obuf, "PMGNWPL,%4.3f,%c,%09.3f,%c,%07.lf,M,%-.*s,%-.46s,%s", lat, ilat < 0 ? 'S' : 'N', lon, ilon < 0 ? 'W' : 'E', waypointp->altitude == unknown_alt ? 0 : waypointp->altitude, + wpt_len, owpt, odesc, icon_token); @@ -1332,7 +1379,8 @@ mag_route_trl(const route_head * rte) thisline++; sprintf(obuff, "PMGNRTE,%d,%d,c,%d,%s,%s", - numlines, thisline, route_out_count, + numlines, thisline, + rte->rte_num ? rte->rte_num : route_out_count, buff1, buff2); mag_writemsg(obuff); @@ -1363,7 +1411,11 @@ mag_write(void) * Whitespace is actually legal, but since waypoint name length is * only 8 bytes, we'll conserve them. */ + setshort_whitespace_ok(mkshort_handle, 0); + + wptcmtcnt = 0; + switch (global_opts.objective) { case trkdata: @@ -1386,6 +1438,7 @@ mag_write(void) */ ff_vecs_t mag_svecs = { ff_type_serial, + FF_CAP_RW_ALL, mag_rd_init, mag_wr_init, mag_deinit, @@ -1398,6 +1451,7 @@ ff_vecs_t mag_svecs = { ff_vecs_t mag_fvecs = { ff_type_file, + FF_CAP_RW_ALL, mag_rd_init, mag_wr_init, mag_deinit, @@ -1407,3 +1461,18 @@ ff_vecs_t mag_fvecs = { NULL, mag_fargs }; + +/* + * Extended (Explorist) entry tables. + */ +ff_vecs_t magX_fvecs = { + ff_type_file, + FF_CAP_RW_ALL, + mag_rd_init, + magX_wr_init, + mag_deinit, + mag_deinit, + mag_read, + mag_write, + NULL, +}; diff --git a/main.c b/main.c index 78acd8dfe..2b1afdfe4 100644 --- a/main.c +++ b/main.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2002 Robert Lipe, robertlipe@usa.net + Copyright (C) 2002-2005 Robert Lipe, robertlipe@usa.net This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -38,6 +38,7 @@ usage(const char *pname, int shorter) " The input type and filename are specified with the -i INTYPE\n" " and -f INFILE options. The output type and filename are specified\n" " with the -o OUTTYPE and -F OUTFILE options.\n" +" If '-' is used for INFILE or OUTFILE, stdin or stdout will be used.\n" "\n" " In the second form of the command, INFILE and OUTFILE are the\n" " first and second positional (non-option) arguments.\n" @@ -202,7 +203,19 @@ main(int argc, char *argv[]) global_opts.masked_objective |= RTEDATAMASK; break; case 'N': - global_opts.no_smart_icons = 1; + switch(argv[argn][2]) { + case 'i': + global_opts.no_smart_icons = 1; + break; + case 'n': + global_opts.no_smart_names = 1; + break; + default: + global_opts.no_smart_names = 1; + global_opts.no_smart_icons = 1; + break; + } + break; case 'x': optarg = argv[argn][2] @@ -236,6 +249,7 @@ main(int argc, char *argv[]) case 'v': switch(argv[argn][2]) { case 's': global_opts.verbose_status = 1; break; + case 'S': global_opts.verbose_status = 2; break; } break; diff --git a/make-an1sym.pl b/make-an1sym.pl new file mode 100644 index 000000000..5af6814be --- /dev/null +++ b/make-an1sym.pl @@ -0,0 +1,361 @@ +#!/usr/bin/perl + +=pod + + This script reads the DeLorme Stock Symbols .dim file and writes code + to be included in the .an1 format handler. + + You MUST have a copy of the DeLorme .dim file; you can download it + from the support section of DeLorme's Web site. You want the one + that contains all of the symbols. + + To use this script: + + perl make-an1sym.pl an1sym.h + + Copyright (C) 2005 Ronald L. Parker (babelan1perl@parkrrrr.com) + and Robert Lipe + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + +=cut + +# read a data structure from the input file. +sub shiftunpack { + my $pattern = shift; + my @result = unpack( $pattern, $file ); + my $str = pack( $pattern, @result ); + $file = substr( $file, length( $str )); + @result; +} + +sub skip_bytes { + my $count = shift; + $file = substr( $file, $count ); +} + +sub decodeGuid { + @guid = unpack( 'LSSSCCCCCC', shift ); + my $sub = undef; + my $guid2 = sprintf( '{0x%8.8x,{0x%4.4x, 0x%4.4x, 0x%4.4x},'. + ' {0x%2.2x, 0x%2.2x, 0x%2.2x, 0x%2.2x, 0x%2.2x, 0x%2.2x}}', + @guid ); + $sub = $substitutions{ sprintf('%8.8x', @guid)}; + ($guid2, $sub); +} + +sub DoImage { + # image information - the 'type' we read was actually the low word of the hotspot X coord. + ($hotspotxhi, $hotspoty, $unk1, $guid, $name ) = + shiftunpack( 'slla[16]C/a*' ); + $hotspotx = $rec_type + 0x10000*$hotspotxhi; + + ($guid2,$sub) = decodeGuid( $guid ); + $name = $sub if ( $sub ); + print qq( {$guid2,\n "$name"},\n); +} + +%substitutions = ( + # everything up to and including "mud" is defined + "012dfac2", "Tractor", + "012dfac3", "Combine Harvester", + "012dfac7", "Front-End Loader", + "fd163780", "Power Shovel", + "fd163781", "Road Grader", + "fd163784", "Road Roller", + "fd163787", "Dump Truck", + "5673d712", "Skid-Steer Loader", # Bobcat is a registered trademark + "b86045ac", "Highway Sign", + "1e129e95", "Orange Cone", + "adee7d54", "Barricade", + "a170000f", "Flagger", + "a425f90e", "Construction Sign", + "0805b240", "Construction Flasher", + "56721a6c", "Transit", + # this group of 8 arrows is defined + "83f91421", "Small Arrow Left", + "83f91422", "Small Arrow Right", + "83f91423", "Small Arrow Up", + "83f91424", "Small Arrow Down", + "83f91425", "Small Arrow Up Left", + "83f91426", "Small Arrow Up Right", + "83f91427", "Small Arrow Down Left", + "83f91428", "Small Arrow Down Right", + "83f91429", "Large Arrow Left", + "83f9142a", "Large Arrow Right", + "83f9142b", "Large Arrow Up", + "83f9142c", "Large Arrow Down", + "83f9142d", "Large Arrow Down Right", + "83f9142e", "Large Arrow Down Left", + "83f9142f", "Large Arrow Up Left", + "83f91430", "Large Arrow Up Right", + "8ff0aad1", "Accommodation", + "af7bf199", "Australia", + "6bbcc9d1", "Blue Dome Cross", + "fff920fe", "Green Dome Cross", + "57e75924", "Business", + "b09ef4a7", "Airplane", + "f2833c22", "Amusement Recreation", # tent? on a green background + "6f0317d6", "Green Square", + "18a6d3c0", "Red Triangle", + "86e68ea7", "Red Triangle and Green Square", + "6afd74bf", "City 4", + "49dfeb74", "White Square", + "3eed62c6", "White Triangle", + "6b521940", "Red Black Diamond Flag", + "bb8ebaa3", "Yellow Diamond Flag", + "8e118862", "Small Pink Square", + "d0ef64c2", "Store", + "a22b08fb", "Camping", + "27f57c69", "Green Diamond Flag", + "e07abb38", "Red Diamond Flag", + "3a124ac9", "Red Green Diamond Flag", + "64ed669b", "White Globe", + "3cb10adc", "Yellow Globe", + "2779347d", "", #??? + "3ad63f7b", "Black Cross", + "3e89481e", "Church", + "68622c10", "Small Dark Green Square", + "42c6a873", "Small Black Square", + "50e3b06e", "Danger", + "369d0b22", "Construction Business", + "10603b6c", "Airport", + "8328aab7", "City 5", + "96411287", "USA", + "b2f98627", "Diver Down", + "3fce26d0", "Light Yellow Square", + "b4b68597", "Education Technology", + "35d2e6a8", "Computer", + "4ddc4e96", "Amusement Recreation Red", + "79f58929", "Telephone Red", + "0083b377", "Exit", + "0c232891", "Exit with Services", + "af63e7c2", "Pizza", + "d419c693", "Financial Services", + "70740a81", "City 3", + "9a582ff6", "Food Store", + "3cd31689", "", #??? + "952557a6", "", #??? white/black circle + "03dc278c", "Driving Range", + "acd28bab", "Golf Municipal", + "984e7139", "Golf Private", + "ec5828ab", "Golf Public", + "b0120d99", "Golf Resort", + "2ce7685a", "Golf Semi Private", + "10397049", "Medical Service", + "2fc28df6", "Home Furnishings", + "910313db", "Industrial", + "9e442c6e", "", #??? + "37e2fe4a", "", #??? + "3c756e09", "", #??? + "a1245b1c", "Manufacturing", + "5bddbd7a", "Note", + "cb6777e1", "City", + "bc168c08", "Air Base", + "a8857b0f", "Battlefield", + "06db55c1", "Mining", + "cc61b277", "Mountain", + "fde13186", "Capital", + "b14d90d1", "Route", + "7eabc63f", "Overnight", + "ac39d8b9", "Route End Active", + "e1b9d86b", "Route End Inactive", + "98712315", "Fuel Stop", + "e5ea5b38", "Route Start Active", + "18fd0d49", "Route Start Inactive", + "2f52144b", "Route Stop Active", + "faf8d826", "Route Stop Inactive", + "ff44cae2", "Route Via", + "5a50d59b", "Radiation Green", + "19556023", "Radiation Red", + "a54be251", "Electricity", + "d793ff0c", "Personal Furnishings", + "00f90733", "Personal Services", + "ea677f24", "Telephone Black", + "2d8a05b5", "Government Light", + "40c64dfc", "Airport Red Square", + "f27adb5d", "Propeller Aircraft", + "5a718e13", "Jet Aircraft", + "0a471039", "Government", + "4a59da2f", "USA Regional", + "f16500a9", "House 2", + "7b05524d", "Picnic", + "b88ad7a1", "Restaurant", + "dc48a20a", "Store 2", + "6b5ab040", "", # ??? + "153b2cff", "Blue Star", + "f276f6b3", "", # ??? + "91d242c8", "Running", + "8b0078db", "Transportation", + "0599f6c9", "Fishing", + "7389128c", "Automotive", + "0362b593", "Cloudy", + "f0717a94", "Partly Cloudy", + "14486bbc", "Mostly Cloudy", + "7a258c70", "Tornado", + "eff260d4", "Lightning", + "c3d70220", "Rain", + # everything else is defined + # They defined two red flags. Ooops. + "f2dfbc95", "Red Flag 2" +); + +sub print_header { +print <<'END'; +/* + + + + + + + + + + THIS FILE IS AUTOMATICALLY GENERATED + + + Please change make-an1sym.pl and + regenerate it rather than changing + this file directly. + + + + + + + + + + + + + + + + + + + + + + + +*/ + +/* + Read DeLorme drawing files (.an1) - supplemental (included by an1.c) + + Copyright (C) 2005 Ron Parker and Robert Lipe. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + + */ + +struct defguid { + GUID guid; + char *name; +} default_guids[] = { +END +} + +sub print_footer { +print <<'END'; +}; + +int FindIconByName( const char *name, GUID *guid ) { + int i = 0; + for ( i = 0; i < (sizeof(default_guids)/sizeof(struct defguid)); i++ ) + { + if ( !case_ignore_strcmp(name, default_guids[i].name)) { + memcpy( guid, &(default_guids[i].guid), sizeof(GUID)); + return 1; + } + } + return 0; +} + +int FindIconByGuid( GUID *guid, char **name ) { + int i = 0; + for ( i = 0; i < (sizeof(default_guids)/sizeof(struct defguid)); i++ ) + { + if ( !memcmp(guid, &default_guids[i].guid, sizeof(GUID))) { + *name = default_guids[i].name; + return 1; + } + } + return 0; +} +END +} + + +# read file +undef $/; +$file = <>; + +# read file header +($magic, $unk1 ) = shiftunpack( 'ss' ); + +# read bitmap info +($unk2) = shiftunpack( 'l' ); + +print_header; + +while ( length($file) ) { + ($rec_type) = shiftunpack( 's' ); + if ( $rec_type == 0x4c49 ) { # 'IL' + # I don't know what this structure is, but it appears twice in my test files. + ($unk10101, $unke, $unkc, $unk18_1, $unk18_2, $unkneg1_1, + $unk20, $unkneg1_2, $unkneg1_3) = shiftunpack( 'lsssslsll'); + } + elsif ( $rec_type == 0x4d42 ) { # 'BM' + # This is a standard BMP file, documented in MSDN. + # BITMAPFILEHEADER + ($fhsize, $res_0_1, $res_0_2, $bitoffset) = shiftunpack( 'lssl' ); + # BITMAPINFOHEADER + ($bmisize, $width, $height, $planes, $bpp, $compression, + $size, $xppm, $yppm, $colused, $colimprt ) = shiftunpack( 'lllssllllll'); + # palette + $palettesize = $bitoffset - $bmisize - 14; # 14 bytes in BMFH, including the 'BM' + skip_bytes( $palettesize ); + # image + skip_bytes( $size ); + } + elsif ($rec_type == 0 ) { # crap + ($a, $b, $c, $d, $e, $f) = shiftunpack( 'llllll' ); + if ( $c ) { + $file = pack( 'llllll', ($a, $b, $c, $d, $e, $f)) . $file; + DoImage; + } + } + else { + DoImage; + } +} + +print_footer; diff --git a/mapopolis.c b/mapopolis.c index fecb23f87..55e73bd76 100644 --- a/mapopolis.c +++ b/mapopolis.c @@ -149,7 +149,7 @@ decode(char *buf) // for(pdb_rec = pdb->rec_index.rec; pdb_rec; pdb_rec=pdb_rec->next) { for(pdb_rec=pdb_rec->next; pdb_rec; pdb_rec=pdb_rec->next) { waypoint *wpt_tmp; - char *vdata; + char *vdata = 0; char *edata; struct tm tm = {0}; @@ -157,7 +157,7 @@ decode(char *buf) edata = (char *) rec + pdb_rec->data_len; for (; vdata < edata; rec = (struct record *) vdata) { - wpt_tmp = xcalloc(sizeof(*wpt_tmp),1); + wpt_tmp = waypt_new(); wpt_tmp->latitude = Lat1 + be_read16(&rec->lat1d) / LATDIV2; wpt_tmp->longitude = Lon1 + @@ -266,8 +266,6 @@ my_writewpt(const waypoint *wpt) static void data_write(void) { - queue *elem, *tmp; - static char *appinfo = "\0\x01" "User\0\0\0\0\0\0\0\0\0\0\0\0" @@ -311,6 +309,7 @@ data_write(void) ff_vecs_t mapopolis_vecs = { ff_type_file, + FF_CAP_RW_WPT, rd_init, wr_init, rd_deinit, diff --git a/mapsend.c b/mapsend.c index 7477a043f..fa538c342 100644 --- a/mapsend.c +++ b/mapsend.c @@ -125,7 +125,7 @@ mapsend_wpt_read(void) my_fread4(&wpt_count, mapsend_file_in); while (wpt_count--) { - wpt_tmp = xcalloc(sizeof(*wpt_tmp), 1); + wpt_tmp = waypt_new(); if (fread(&scount, sizeof(scount), 1, mapsend_file_in) < 1) { fatal(MYNAME ": out of data reading %d waypoints\n", @@ -183,7 +183,7 @@ mapsend_wpt_read(void) my_fread4(&wpt_count, mapsend_file_in); while (wpt_count--) { - wpt_tmp = xcalloc(sizeof(*wpt_tmp), 1); + wpt_tmp = waypt_new(); /* waypoint name */ fread(&scount, sizeof(scount), 1, mapsend_file_in); @@ -259,7 +259,7 @@ mapsend_track_read(void) centisecs = 0; } - wpt_tmp = xcalloc(sizeof(*wpt_tmp), 1); + wpt_tmp = waypt_new(); wpt_tmp->latitude = -wpt_lat; wpt_tmp->longitude = wpt_long; wpt_tmp->creation_time = time; @@ -316,21 +316,43 @@ mapsend_waypt_pr(const waypoint *waypointp) static int cnt = 0; const char *iconp = NULL; const char *sn = global_opts.synthesize_shortnames ? - mkshort(mkshort_handle, waypointp->description) : + mkshort_from_wpt(mkshort_handle, waypointp) : waypointp->shortname; + char *tmp; - c = sn ? strlen(sn) : 0; + /* + * The format spec doesn't call out the character set of waypoint + * name and description. Empirically, we can see that it's 8859-1, + * but if we create mapsend files containing those, Mapsend becomes + * grumpy uploading the resulting waypoints and being unable to deal + * with the resulting comm errors. + * + * Ironically, our own Magellan serial module strips the "naughty" + * characters, keeping it more in definition with their own serial + * spec. :-) + * + * So we just decompose the utf8 strings to ascii before stuffing + * them into the Mapsend file. + */ + + tmp = str_utf8_to_ascii(sn); + c = tmp ? strlen(tmp) : 0; fwrite(&c, 1, 1, mapsend_file_out); - fwrite(sn, c, 1, mapsend_file_out); + fwrite(tmp, c, 1, mapsend_file_out); + if (tmp) + xfree(tmp); - if (waypointp->description) - c = strlen(waypointp->description); + tmp = str_utf8_to_ascii(waypointp->description); + if (tmp) + c = strlen(tmp); else c = 0; if (c > 30) c = 30; fwrite(&c, 1, 1, mapsend_file_out); - fwrite(waypointp->description, c, 1, mapsend_file_out); + fwrite(tmp, c, 1, mapsend_file_out); + if (tmp) + xfree(tmp); /* #, icon, status */ n = ++cnt; @@ -522,7 +544,7 @@ void mapsend_track_disp(const waypoint * wpt) my_fwrite8(&dbl, mapsend_file_out); /* altitude */ - i = wpt->altitude; + i = (int) wpt->altitude; my_fwrite4(&i, mapsend_file_out); /* time */ @@ -584,6 +606,7 @@ mapsend_wpt_write(void) ff_vecs_t mapsend_vecs = { ff_type_file, + FF_CAP_RW_ALL, mapsend_rd_init, mapsend_wr_init, mapsend_rd_deinit, diff --git a/mapsource.c b/mapsource.c index d303814ac..948d76084 100644 --- a/mapsource.c +++ b/mapsource.c @@ -95,6 +95,7 @@ arglist_t mps_args[] = { * A wrapper to ensure the doubles we fwrite are in correct endianness. */ +void le_fwrite64(void *ptr, int sz, int ct, FILE *stream) { unsigned char cbuf[8]; @@ -107,6 +108,7 @@ le_fwrite64(void *ptr, int sz, int ct, FILE *stream) fwrite(cbuf, 8, 1, stream); } +void le_fread64(void *ptr, int sz, int ct, FILE *stream) { unsigned char cbuf[8]; @@ -411,7 +413,7 @@ mps_fileHeader_r(FILE *mps_file, int *mps_ver) static void mps_fileHeader_w(FILE *mps_file, int mps_ver) { - char hdr[100]; + unsigned char hdr[100]; int reclen; strcpy (hdr, "MsRc"); @@ -467,10 +469,10 @@ mps_fileHeader_w(FILE *mps_file, int mps_ver) static void mps_mapsegment_r(FILE *mps_file, int mps_ver) { - char hdr[100]; int reclen; /* At the moment we're not doing anything with map segments, but here's the template code as if we were + char hdr[100]; fread(&CDid, 4, 1, mps_file); reclen = le_read32(&CDid); @@ -499,10 +501,10 @@ mps_mapsegment_r(FILE *mps_file, int mps_ver) static void mps_mapsetname_r(FILE *mps_file, int mps_ver) { - char hdr[100]; int reclen; /* At the moment we're not doing anything with mapsetnames, but here's the template code as if we were + char hdr[100]; mps_readstr(mps_file, hdr, sizeof(hdr)); char mapsetnamename[very large number?]; strcpy(mapsetnamename,hdr); @@ -857,7 +859,7 @@ mps_route_wpt_w_unique_wrapper(const waypoint *wpt) } } } - +#if 0 /* * wrapper to include the mps_ver_out information * This one always writes a waypoint. If it has been written before @@ -869,7 +871,6 @@ mps_waypoint_w_uniqloc_wrapper(waypoint *wpt) { waypoint *wptfound = NULL; char *newName; - unsigned int uniqueNum = 0; /* Search for this waypoint in the ones already written */ wptfound = mps_find_wpt_q_by_name(&written_wpt_head, wpt->shortname); @@ -901,6 +902,7 @@ mps_waypoint_w_uniqloc_wrapper(waypoint *wpt) mps_wpt_q_add(&written_wpt_head, wpt); } } +#endif /* * read in from file a route record @@ -918,9 +920,7 @@ mps_route_r(FILE *mps_file, int mps_ver, route_head **rte) int interlinkStepCount; int thisInterlinkStep; unsigned int mpsclass; - int FFsRead; - time_t dateTime = 0; route_head *rte_head; int rte_count; @@ -1177,7 +1177,6 @@ mps_routehdr_w(FILE *mps_file, int mps_ver, const route_head *rte) { unsigned int reclen; unsigned int rte_datapoints; - unsigned int colour = 0; /* unknown colour */ int rname_len; char *rname; char hdr[20]; @@ -1317,7 +1316,6 @@ mps_routehdr_w(FILE *mps_file, int mps_ver, const route_head *rte) fwrite(zbuf, 9, 1, mps_file); } else { - unsigned char cbuf[8]; hdr[0] = 1; fwrite(hdr, 1 , 1, mps_file); @@ -1346,7 +1344,6 @@ mps_routedatapoint_w(FILE *mps_file, int mps_ver, const waypoint *rtewpt) unsigned char hdr[10]; int lat; int lon; - time_t t = rtewpt->creation_time; char zbuf[20]; char ffbuf[20]; char *src; @@ -1912,6 +1909,8 @@ mps_write(void) int reclen; int reclen2; unsigned int tocopy; + unsigned int block; + long tempFilePos; unsigned int mpsWptClass; @@ -1988,9 +1987,10 @@ mps_write(void) fseek(mps_file_temp, tempFilePos, SEEK_SET); /* copy the data using a "reasonably" sized buffer */ - for(tocopy = reclen2; tocopy > 0; tocopy -= sizeof(copybuf)) { - fread(copybuf, (tocopy > sizeof(copybuf) ? sizeof(copybuf) : tocopy), 1, mps_file_temp); - fwrite(copybuf, (tocopy > sizeof(copybuf) ? sizeof(copybuf) : tocopy), 1, mps_file_out); + for(tocopy = reclen2; tocopy > 0; tocopy -= block) { + block = (tocopy > sizeof(copybuf) ? sizeof(copybuf) : tocopy); + fread(copybuf, block, 1, mps_file_temp); + fwrite(copybuf, block, 1, mps_file_out); } } else break; @@ -2026,6 +2026,7 @@ mps_write(void) /* prior to writing any tracks as requested, if we're doing a merge, read in the rtes from the original file and then write them out, ready for tracks to follow */ + /* if ((mpsmergeout) && (global_opts.objective != rtedata)) { */ if ((mpsmergeout) && (! doing_rtes)) { while (!feof(mps_file_temp)) { @@ -2035,9 +2036,11 @@ mps_write(void) fwrite(&reclen, 4, 1, mps_file_out); /* write out untouched */ fwrite(&recType, 1, 1, mps_file_out); - for(tocopy = reclen2; tocopy > 0; tocopy -= sizeof(copybuf)) { - fread(copybuf, (tocopy > sizeof(copybuf) ? sizeof(copybuf) : tocopy), 1, mps_file_temp); - fwrite(copybuf, (tocopy > sizeof(copybuf) ? sizeof(copybuf) : tocopy), 1, mps_file_out); + /* copy the data using a "reasonably" sized buffer */ + for(tocopy = reclen2; tocopy > 0; tocopy -= block) { + block = (tocopy > sizeof(copybuf) ? sizeof(copybuf) : tocopy); + fread(copybuf, block, 1, mps_file_temp); + fwrite(copybuf, block, 1, mps_file_out); } } else break; @@ -2095,9 +2098,11 @@ mps_write(void) fwrite(&reclen, 4, 1, mps_file_out); /* write out untouched */ fwrite(&recType, 1, 1, mps_file_out); - for(tocopy = reclen2; tocopy > 0; tocopy -= sizeof(copybuf)) { - fread(copybuf, (tocopy > sizeof(copybuf) ? sizeof(copybuf) : tocopy), 1, mps_file_temp); - fwrite(copybuf, (tocopy > sizeof(copybuf) ? sizeof(copybuf) : tocopy), 1, mps_file_out); + /* copy the data using a "reasonably" sized buffer */ + for(tocopy = reclen2; tocopy > 0; tocopy -= block) { + block = (tocopy > sizeof(copybuf) ? sizeof(copybuf) : tocopy); + fread(copybuf, block, 1, mps_file_temp); + fwrite(copybuf, block, 1, mps_file_out); } } else break; @@ -2140,10 +2145,13 @@ mps_write(void) fwrite(&reclen, 4, 1, mps_file_out); /* write out untouched */ fwrite(&recType, 1, 1, mps_file_out); - for(tocopy = reclen2; tocopy > 0; tocopy -= sizeof(copybuf)) { - fread(copybuf, (tocopy > sizeof(copybuf) ? sizeof(copybuf) : tocopy), 1, mps_file_temp); - fwrite(copybuf, (tocopy > sizeof(copybuf) ? sizeof(copybuf) : tocopy), 1, mps_file_out); + /* copy the data using a "reasonably" sized buffer */ + for(tocopy = reclen2; tocopy > 0; tocopy -= block) { + block = (tocopy > sizeof(copybuf) ? sizeof(copybuf) : tocopy); + fread(copybuf, block, 1, mps_file_temp); + fwrite(copybuf, block, 1, mps_file_out); } + if (recType != 'V') { fread(&reclen, 4, 1, mps_file_temp); reclen2 = le_read32(&reclen); @@ -2163,6 +2171,7 @@ mps_write(void) ff_vecs_t mps_vecs = { ff_type_file, + FF_CAP_RW_ALL, mps_rd_init, mps_wr_init, mps_rd_deinit, diff --git a/mingw/Makefile b/mingw/Makefile index f5833cb7d..0bbea79a2 100644 --- a/mingw/Makefile +++ b/mingw/Makefile @@ -1,7 +1,7 @@ CC=/usr/local/cross-tools/bin/i386-mingw32msvc-gcc VPATH=..:../shapelib -FILES=gpsbabel.exe libexpat.dll ../win32/gpsbabelfront.exe ../README* ../COPYING +FILES=gpsbabel.exe libexpat.dll ../win32/GPSBabelGUI.exe ../README* ../COPYING gpsbabel.exe: wintesto.cmd @@ -24,3 +24,17 @@ mkwintesto: mkwintesto.c wintesto.cmd: mkwintesto ./mkwintesto ../testo + +# The "usbfree" target is useful for generating an executable that +# works on NT 3.5 or 4.0 since it doesn't have USB support and tanks +# on our libsetupapi references. + +usbfree: + $(MAKE) INHIBIT_USB=-DNO_USB gpsbabel-usbfree.exe + +gpsbabel-usbfree.exe: $(OBJS) + $(CC) -static $(CFLAGS) $(OBJS) lib/libexpat.a -o gpsbabel-usbfree.exe + zip -j /tmp/gpsbabel-nousb-$(VERSIOND).zip gpsbabel-usbfree.exe + + + diff --git a/mingw/wintesto.cmd b/mingw/wintesto.cmd index e58576b30..0df95a78d 100644 --- a/mingw/wintesto.cmd +++ b/mingw/wintesto.cmd @@ -126,6 +126,27 @@ DEL %TMPDIR%\tiger @echo. CALL :COMPARE %TMPDIR%\tiger %TMPDIR%\tiger2 +REM +REM Lowrance USR. Binary, and also slightly lossy because of the math to +REM convert lat/long. It also doesn't support description, which makes it +REM awkward to test. +REM +DEL %TMPDIR%\lowrance1.usr +@echo on +@echo Testing... +%PNAME% -i geo -f geocaching.loc -o lowranceusr -F %TMPDIR%\lowrance1.usr +@echo off +@echo. +CALL :BINCOMPARE %TMPDIR%\lowrance1.usr reference\lowrance.usr +@echo on +@echo Testing... +%PNAME% -i lowranceusr -f %TMPDIR%\lowrance1.usr -o lowranceusr -F %TMPDIR%\lowrance1.usr +@echo off +@echo. +REM And because of the FP rounding, we can't even read our file, write it back +REM and get the same data. Sigh. +REM bincompare reference/lowrance.usr ${TMPDIR}/lowrance1.usr + REM CSV (Comma separated value) data. @echo on @@ -250,7 +271,7 @@ REM identical reference. %PNAME% -i holux -f reference\paris.wpo -o holux -F %TMPDIR%\paris.wpo @echo off @echo. -CALL :COMPARE reference\paris.wpo %TMPDIR%\paris.wpo +REM compare reference/paris.wpo ${TMPDIR}/paris.wpo REM Magellan NAV Companion for PalmOS REM This format is hard to test, because each record and the database itself @@ -582,6 +603,34 @@ REM Navicache. CALL :COMPARE %TMPDIR%\navi.wpt reference\navicache.ref REM +REM +REM CoastalExplorer.. +@echo on +@echo Testing... +%PNAME% -r -i coastexp -f reference\coastexp.nob -o gpx -F %TMPDIR%\coastexp.gpx +@echo off +@echo. +CALL :COMPARE %TMPDIR%\coastexp.gpx reference\coastexp.ref +@echo on +@echo Testing... +%PNAME% -r -i gpx -f %TMPDIR%\coastexp.gpx -o coastexp -F %TMPDIR%\coastexp.nob +@echo off +@echo. +CALL :COMPARE %TMPDIR%\coastexp.nob reference\coastexp.ref2 +@echo on +@echo Testing... +%PNAME% -w -i coastexp -f reference\coastexp.nob -o gpx -F %TMPDIR%\coastexp.gpx +@echo off +@echo. +CALL :COMPARE %TMPDIR%\coastexp.gpx reference\coastexp.ref3 +@echo on +@echo Testing... +%PNAME% -w -i gpx -f %TMPDIR%\coastexp.gpx -o coastexp -F %TMPDIR%\coastexp.nob +@echo off +@echo. +CALL :COMPARE %TMPDIR%\coastexp.nob reference\coastexp.ref4 +REM + REM PsiTrex. A text format that can't be handled by XCSV due to context of REM data based on other data values in the file REM Waypoints first @@ -809,6 +858,87 @@ CALL :COMPARE %TMPDIR%\igc_sed.out reference\igc2_igc.out @echo. CALL :COMPARE %TMPDIR%\igc.gpx reference\igc2_gpx.out +REM +REM Google Maps XML test +REM +DEL %TMPDIR%\google.out +@echo on +@echo Testing... +%PNAME% -i google -f reference\google.xml -o arc -F %TMPDIR%\google.out +@echo off +@echo. +CALL :COMPARE %TMPDIR%\google.out reference\google.arc + +DEL %TMPDIR%\google.out +@echo on +@echo Testing... +%PNAME% -i google -f reference\google.js -o arc -F %TMPDIR%\google.out +@echo off +@echo. +CALL :COMPARE %TMPDIR%\google.out reference\google.arc + +REM +REM DeLorme .an1 tests +REM +DEL %TMPDIR%\an1.out +@echo on +@echo Testing... +%PNAME% -i an1 -f reference\foo.an1 -o csv -F %TMPDIR%\an1.out +@echo off +@echo. +CALL :COMPARE %TMPDIR%\an1.out reference\an1-in.ref + +DEL %TMPDIR%\an1.out +@echo on +@echo Testing... +%PNAME% -i an1 -f reference\foo.an1 -o an1 -F %TMPDIR%\an1.out +@echo off +@echo. +CALL :COMPARE %TMPDIR%\an1.out reference\an1-an1.ref + +DEL %TMPDIR%\an1.out +@echo on +@echo Testing... +%PNAME% -i xmap -f reference\xmap -o an1 -F %TMPDIR%\an1.out +@echo off +@echo. +CALL :COMPARE %TMPDIR%\an1.out reference\an1-out.ref + +DEL %TMPDIR%\an1.out +@echo on +@echo Testing... +%PNAME% -i google -f reference\google.js -o an1 -F %TMPDIR%\an1.out +@echo off +@echo. +CALL :COMPARE %TMPDIR%\an1.out reference\an1-line-out.ref + +REM +REM TomTom .ov2 tests +REM + +DEL %TMPDIR%\ov2.out +@echo on +@echo Testing... +%PNAME% -i arc -f reference\google.arc -o tomtom -F %TMPDIR%\ov2.out +@echo off +@echo. +CALL :COMPARE %TMPDIR%\ov2.out reference\ov2-arc-out.ref + +DEL %TMPDIR%\ov2.out +@echo on +@echo Testing... +%PNAME% -i geo -f reference\gl.loc -o tomtom -F %TMPDIR%\ov2.out +@echo off +@echo. +CALL :COMPARE %TMPDIR%\ov2.out reference\ov2-geo-out.ref + +DEL %TMPDIR%\ov2.out +@echo on +@echo Testing... +%PNAME% -i tomtom -f reference\ov2-geo-out.ref -o gpsutil -F %TMPDIR%\ov2.out +@echo off +@echo. +CALL :COMPARE %TMPDIR%\ov2.out reference\ov2-in.ref REM REM XCSV "human readable" tests @@ -873,3 +1003,36 @@ REM @echo off @echo. +REM +REM 'tabsep' isn't really tested in any non-trivial way, but we do exercise +REM it. +REM + +@echo on +@echo Testing... +%PNAME% -i geo -f geocaching.loc -o tabsep -F - | ${PNAME} -i tabsep -f - -o geo -F %TMPDIR%\tabsep.out +%PNAME% -i geo -f geocaching.loc -o geo -F %TMPDIR%\geotabsep.out +@echo off +@echo. + +REM +REM Now do the same for custom - it has the same issues. +REM + +CALL :COMPARE %TMPDIR%\tabsep.out %TMPDIR%\geotabsep.out +@echo on +@echo Testing... +%PNAME% -i geo -f geocaching.loc -o custom -F - | ${PNAME} -i custom -f - -o geo -F %TMPDIR%\custom.out +%PNAME% -i geo -f geocaching.loc -o geo -F %TMPDIR%\geocustom.out +@echo off +@echo. + +REM +REM Write something to the various output-only formats +REM +@echo on +@echo Testing... +%PNAME% -i geo -f geocaching.loc -o text -F %TMPDIR%\text.out -o html -F %TMPDIR%\html.out -o vcard -F %TMPDIR%\vcard.out #-o palmdoc -F %TMPDIR%\pd.out +@echo off +@echo. + diff --git a/mkshort.c b/mkshort.c index 15d69bcea..ce45907b8 100644 --- a/mkshort.c +++ b/mkshort.c @@ -43,6 +43,7 @@ typedef struct { int whitespaceok; unsigned int target_len; char *badchars; + char *goodchars; int must_uniq; queue namelist[PRIME]; int depth[PRIME]; @@ -149,18 +150,25 @@ mkshort_del_handle(void *h) mkshort_handle *hdr = h; int i; - if (hdr) { - for (i = 0; i < PRIME; i++) { - queue *e, *t; - QUEUE_FOR_EACH(&hdr->namelist[i], e, t) { - uniq_shortname *s = (uniq_shortname *) e; - dequeue(e); - xfree(s->orig_shortname); - xfree(s); + if (!hdr) + return; + + for (i = 0; i < PRIME; i++) { + queue *e, *t; + QUEUE_FOR_EACH(&hdr->namelist[i], e, t) { + uniq_shortname *s = (uniq_shortname *) e; +#if 0 + if (global_opts.verbose_status >= 2 && s->conflictctr) { + fprintf(stderr, "%d Output name conflicts: '%s'\n", + s->conflictctr, s->orig_shortname); } +#endif + dequeue(e); + xfree(s->orig_shortname); + xfree(s); } - xfree(hdr); } + xfree(hdr); } /* @@ -179,8 +187,10 @@ delete_last_vowel(int start, char *istring, int *replaced) *replaced = 0; for (l = strlen(istring); l > start; l--) { if (strchr(vowels, istring[l-1])) { - char *ostring = xstrdup(istring); - + char *ostring; + /* If vowel is the first letter of a word, keep it.*/ + if (istring[l-2] == ' ') continue; + ostring = xstrdup(istring); strncpy(&ostring[l-1], &istring[l], 1+strlen(istring)-l); ostring[strlen(istring)-1] = 0; *replaced = 1; @@ -230,6 +240,13 @@ setshort_badchars(void *h, const char *s) hdl->badchars = xstrdup(s); } } +void +setshort_goodchars(void *h, const char *s) +{ + mkshort_handle *hdl = h; + + hdl->goodchars = xstrdup(s); +} void setshort_mustupper(void *h, int i) @@ -245,7 +262,6 @@ setshort_mustuniq(void *h, int i) hdl->must_uniq = i; } - char * #ifdef DEBUG_MEM MKSHORT(void *h, const char *istring, DEBUG_PARAMS ) @@ -272,21 +288,14 @@ mkshort(void *h, const char *istring) ostring = nstring; } - /* - * Look at the back of the string for " by BLAH" and whack - * it there. - */ - nstring = xxstrdup(ostring, file, line); - l = strlen (nstring); - while (l > 0) { - if (strncmp(&nstring[l], " by ",4) == 0) { - nstring[l] = 0; - break; - } - l --; + /* Eliminate leading whitespace in all cases */ + while (ostring[0] && isspace(ostring[0])) { + /* If orig string has N bytes, we want to copy N-1 bytes + * of the string itself plus the string terminator (which + * matters if the string consists of nothing but spaces) + */ + memmove(&ostring[0], &ostring[1], strlen(ostring)); } - xfree(ostring); - ostring = nstring; if (!hdl->whitespaceok) { /* @@ -319,11 +328,23 @@ mkshort(void *h, const char *istring) for (i=0;ibadchars, tstring[i]) || !isascii(tstring[i])) continue; + if (hdl->goodchars && (!strchr(hdl->goodchars, tstring[i]))) + continue; *cp++ = tstring[i]; } *cp = 0; xfree(tstring); + /* + * Eliminate repeated whitespace. This can only shorten the string + * so we do it in place. + */ + for (i = 0; i < l-1; i++) { + if (ostring[i] == ' ' && ostring[i+1] == ' ') { + memmove(&ostring[i], &ostring[i+1], l-i); + } + } + /* * Toss vowels to approach target length, but don't toss them * if we don't have to. We always keep the leading two letters @@ -351,7 +372,7 @@ mkshort(void *h, const char *istring) * Walk in the Woods 2. */ np = ostring + strlen(ostring); - while (isdigit(*(np-1) )) { + while (*(np-1) && isdigit(*(np-1) )) { np--; } if (np) { @@ -366,12 +387,47 @@ mkshort(void *h, const char *istring) strcpy(&ostring[hdl->target_len] - strlen(np), np); } + /* + * If, after all that, we have an empty string, punt and + * let the must_uniq code handle it. + */ + if (ostring[0] == '\0') { + xfree(ostring); + ostring = xstrdup("WPT"); + } + if (hdl->must_uniq) { return mkshort_add_to_list(hdl, ostring); } return ostring; } +/* + * As above, but arg list is a waypoint so we can centralize + * the code that considers the alternate sources. + */ +char * +mkshort_from_wpt(void *h, const waypoint *wpt) +{ + /* This probably came from a Groundspeak Pocket Query + * so use the 'cache name' instead of the description field + * which contains placer name, diff, terr, and generally way + * more stuff than should be in any one field... + */ + if (wpt->gc_data.diff && wpt->gc_data.terr && wpt->notes) { + return mkshort(h, wpt->notes); + } + + if (wpt->description) { + return mkshort(h, wpt->description); + } + + if (wpt->notes) { + return mkshort(h, wpt->notes); + } +} + + #if 0 char *foo[] = { "VwthPst# 3700.706N 08627.588W 0000000m View the Past #2 ", diff --git a/msvc/GPSBabel.dsp b/msvc/GPSBabel.dsp index 5b1ab443d..45f765dee 100644 --- a/msvc/GPSBabel.dsp +++ b/msvc/GPSBabel.dsp @@ -39,9 +39,10 @@ RSC=rc.exe # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /W3 /GX /O2 /I "expat" /I "..\coldsync" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "__WIN32__" /D VERSION=\"1.2.1_beta01072004_msvc\" /YX /FD /c +# ADD CPP /nologo /W3 /WX /GX /O2 /I "expat" /I "..\coldsync" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "__WIN32__" /D VERSION=\"1.2.1_beta01072004_msvc\" /YX /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe @@ -49,7 +50,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib setupapi.lib /nologo /subsystem:console /machine:I386 !ELSEIF "$(CFG)" == "GPSBabel - Win32 Debug" @@ -62,10 +63,10 @@ LINK32=link.exe # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "expat" /I "..\coldsync" /D "WIN32" /D "__WIN32__" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D VERSION=\"1.2.1_beta01072004_msvc\" /FR /YX /FD /GZ /c -# SUBTRACT CPP /WX +# ADD CPP /nologo /W3 /WX /Gm /GX /ZI /Od /I "expat" /I "..\coldsync" /D "WIN32" /D "__WIN32__" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D VERSION=\"1.2.1_beta01072004_msvc\" /FR /YX /FD /GZ /c # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe @@ -73,7 +74,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib setupapi.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept !ENDIF @@ -224,6 +225,22 @@ SOURCE=..\jeeps\gpsserial.c # End Source File # Begin Source File +SOURCE=..\jeeps\gpsusbread.c +# End Source File +# Begin Source File + +SOURCE=..\jeeps\gpsusbsend.c +# End Source File +# Begin Source File + +SOURCE=..\jeeps\gpsusbstub.c +# End Source File +# Begin Source File + +SOURCE=..\jeeps\gpsusbwin.c +# End Source File +# Begin Source File + SOURCE=..\jeeps\gpsutil.c !IF "$(CFG)" == "GPSBabel - Win32 Release" @@ -270,6 +287,18 @@ SOURCE=..\coldsync\util.c !ENDIF +# End Source File +# End Group +# Begin Group "ShapeLib" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\shapelib\dbfopen.c +# End Source File +# Begin Source File + +SOURCE=..\shapelib\shpopen.c # End Source File # End Group # Begin Source File @@ -278,10 +307,18 @@ SOURCE=..\arcdist.c # End Source File # Begin Source File +SOURCE=..\brauniger_iq.c +# End Source File +# Begin Source File + SOURCE=..\cetus.c # End Source File # Begin Source File +SOURCE=..\coastexp.c +# End Source File +# Begin Source File + SOURCE=..\copilot.c # End Source File # Begin Source File @@ -310,6 +347,10 @@ SOURCE=..\garmin.c # End Source File # Begin Source File +SOURCE=..\garmin_tables.c +# End Source File +# Begin Source File + SOURCE=..\gcdb.c # End Source File # Begin Source File @@ -322,6 +363,14 @@ SOURCE=..\geoniche.c # End Source File # Begin Source File +SOURCE=..\glogbook.c +# End Source File +# Begin Source File + +SOURCE=..\google.c +# End Source File +# Begin Source File + SOURCE=..\gpilots.c # End Source File # Begin Source File @@ -342,6 +391,10 @@ SOURCE=..\grtcirc.c # End Source File # Begin Source File +SOURCE=..\hiketech.c +# End Source File +# Begin Source File + SOURCE=..\holux.c # End Source File # Begin Source File @@ -354,10 +407,22 @@ SOURCE=..\html.c # End Source File # Begin Source File +SOURCE=..\igc.c +# End Source File +# Begin Source File + SOURCE=..\internal_styles.c # End Source File # Begin Source File +SOURCE=..\kml.c +# End Source File +# Begin Source File + +SOURCE=..\lowranceusr.c +# End Source File +# Begin Source File + SOURCE=..\magnav.c # End Source File # Begin Source File @@ -398,6 +463,10 @@ SOURCE=..\nmea.c # End Source File # Begin Source File +SOURCE=..\overlay.c +# End Source File +# Begin Source File + SOURCE=..\ozi.c # End Source File # Begin Source File @@ -446,6 +515,10 @@ SOURCE=..\saroute.c # End Source File # Begin Source File +SOURCE=..\shape.c +# End Source File +# Begin Source File + SOURCE=..\smplrout.c # End Source File # Begin Source File @@ -454,6 +527,10 @@ SOURCE=..\sort.c # End Source File # Begin Source File +SOURCE=..\stackfilter.c +# End Source File +# Begin Source File + SOURCE=..\text.c # End Source File # Begin Source File @@ -478,6 +555,14 @@ SOURCE=..\util_crc.c # End Source File # Begin Source File +SOURCE=..\uuid.c +# End Source File +# Begin Source File + +SOURCE=..\vcf.c +# End Source File +# Begin Source File + SOURCE=..\vecs.c # End Source File # Begin Source File @@ -494,6 +579,10 @@ SOURCE=..\xcsv.c # End Source File # Begin Source File +SOURCE=..\xmlgeneric.c +# End Source File +# Begin Source File + SOURCE=.\Expat\libexpat.lib # End Source File # End Group @@ -600,6 +689,14 @@ SOURCE=..\jeeps\gpsserial.h SOURCE=..\jeeps\gpsutil.h # End Source File # End Group +# Begin Group "ShapeLib-Headers" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\shapelib\shapefil.h +# End Source File +# End Group # Begin Source File SOURCE=..\csv_util.h @@ -636,6 +733,10 @@ SOURCE=..\queue.h SOURCE=..\quovadis.h # End Source File +# Begin Source File + +SOURCE=..\uuid.h +# End Source File # End Group # Begin Group "Resource Files" diff --git a/msvc/GPSBabel.vcproj b/msvc/GPSBabel.vcproj index 8d9f72aea..8d000a790 100644 --- a/msvc/GPSBabel.vcproj +++ b/msvc/GPSBabel.vcproj @@ -33,6 +33,7 @@ ObjectFile=".\Release/" ProgramDataBaseFileName=".\Release/" WarningLevel="3" + WarnAsError="TRUE" SuppressStartupBanner="TRUE" DebugInformationFormat="3" CompileAs="0"/> @@ -40,6 +41,7 @@ Name="VCCustomBuildTool"/> + + + + + + + + + + + + + + + + + + + + + + + + @@ -1518,6 +1558,18 @@ BrowseInformation="1"/> + + + + + + + + + + + + + + + + diff --git a/navicache.c b/navicache.c index 0d42a38ba..eb134c21f 100644 --- a/navicache.c +++ b/navicache.c @@ -256,6 +256,7 @@ nav_write(void) ff_vecs_t navicache_vecs = { ff_type_file, + FF_CAP_RW_WPT, nav_rd_init, nav_wr_init, nav_rd_deinit, diff --git a/netstumbler.c b/netstumbler.c index 1674215e6..242fdb881 100644 --- a/netstumbler.c +++ b/netstumbler.c @@ -293,6 +293,7 @@ fix_netstumbler_dupes(void) ff_vecs_t netstumbler_vecs = { ff_type_file, + { ff_cap_read, ff_cap_none, ff_cap_none }, rd_init, NULL, rd_deinit, diff --git a/nmea.c b/nmea.c index 3b0f136ae..0a6fd3d68 100644 --- a/nmea.c +++ b/nmea.c @@ -439,7 +439,7 @@ nmea_trackpt_pr(const waypoint *wpt) } static void -nmea_write() +nmea_write(void) { waypt_disp_all(nmea_wayptpr); track_disp_all(NULL, NULL, nmea_trackpt_pr); @@ -447,11 +447,13 @@ nmea_write() ff_vecs_t nmea_vecs = { ff_type_file, + { ff_cap_read | ff_cap_write, ff_cap_read | ff_cap_write, ff_cap_none}, nmea_rd_init, nmea_wr_init, nmea_rd_deinit, nmea_wr_deinit, nmea_read, nmea_write, + NULL, NULL }; diff --git a/overlay.c b/overlay.c new file mode 100644 index 000000000..aac9e5cf3 --- /dev/null +++ b/overlay.c @@ -0,0 +1,701 @@ +/* + + Geogrid-Viewer overlay file Version 0.9.3 + + A detail description of the ASCII-overlay-fomat you can find in the + helpfile of Geogrid-Viewer. + + Latest changes at 11.01.2005 by Fredie Kern + + Copyright (C) 2005 Fredie Kern, f.kern@xdesy.de + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + + */ +#include "defs.h" +#include "grtcirc.h" + +static void *mkshort_handle; + +#define MYNAME "overlay" +#define PARAMETER_FILE "overlay.def" + +#undef MAPNAME +#define MAPNAME "Bundesrepublik 1:1 Mio" +#undef MAPNAME +#define MAPNAME "Top. Karte 1:50.000 Nieders." + +static FILE *fpout; +static FILE *fpin; +static int govl_cnt; +static double govl_sum_e=0.0; +static double govl_sum_n=0.0; +static double govl_sumcnt=0.0; +static int govl_symbol_cnt=0; +static int govl_group_cnt=0; +/* +static double govl_last_east=0.0; +static double govl_last_north=0.0; +*/ + +static int govl_col=1; +static char *govl_col_s = NULL; +static int govl_size=101; +static char *govl_size_s = NULL; +static double govl_dir=0.0; + +static char *govl_mapname = NULL; +static int govl_zoomfc = 100; +static char *govl_zoomfc_s = NULL; +static int govl_dimmfc = 100; +static char *govl_dimmfc_s = NULL; + + +static int govl_txtcol=1; +static int govl_txtsize=120; +static int govl_font=1; +static int govl_txttrans=0; + +static char *govl_txtcol_s = NULL; +static char *govl_txtsize_s = NULL; +static char *govl_font_s = NULL; +static char *govl_txttrans_s = NULL; + +static char *govl_file_s = NULL; + +static arglist_t ovl_args[] = { + { "col", &govl_col_s, "color index [1-9] for routes", + NULL, ARGTYPE_INT }, + { "size", &govl_size_s, "size index [101-] for routes", + NULL, ARGTYPE_INT }, + { "mapname", &govl_mapname, "name of map", + NULL, ARGTYPE_STRING }, + { "zoomfc", &govl_zoomfc_s, "zoom factor of map in %", + NULL, ARGTYPE_INT }, + { "dimmfc", &govl_dimmfc_s, "dimmer factor of map in %", + NULL, ARGTYPE_INT }, + { "txtcol", &govl_txtcol_s, "color index [1-9] for waypoint names", + NULL, ARGTYPE_INT }, + { "txtsize", &govl_txtsize_s, "text size [101-] for waypoint names", + NULL, ARGTYPE_INT }, + { "font", &govl_font_s, "font index [1-] for waypoint names", + NULL, ARGTYPE_INT }, + { "txttrans", &govl_txttrans_s, "set text background to transparent", + NULL, ARGTYPE_BOOL }, + { "file", &govl_file_s, "use file of parameters (parameters on command line overwrites file parameters)", + NULL, ARGTYPE_STRING }, + { 0, 0, 0, 0, 0 } +}; + + +static char *Keywords[]={ + "Typ", + "Group", + "Col", + "Zoom", + "Size", + "Art", + "Punkte", + "Path", + "Dir", + "Font", + "Area", + "Text", + "Width", + "Height", + "Trans", + "TransByte", + NULL + }; + +#define KEY_TYP 0 +#define KEY_GROUP 1 +#define KEY_COL 2 +#define KEY_ZOOM 3 +#define KEY_SIZE 4 +#define KEY_ART 5 +#define KEY_PUNKTE 6 +#define KEY_PATH 7 +#define KEY_DIR 8 +#define KEY_FONT 9 +#define KEY_AREA 10 +#define KEY_TEXT 11 +#define KEY_WIDTH 12 +#define KEY_HEIGHT 13 +#define KEY_TRANS 14 +#define KEY_TRANSBYTE 15 + +static int isKeyword(char *str,char **keys) +{ + int i; + + i = 0; + while(keys[i]!=NULL && strcmp(str,keys[i])) i++; + return(keys[i]==NULL ? -1 : i); +} + +/*----------------------------------------------*/ + +void ovl_rd_init(char const *fname) +{ + fpin = xfopen(fname, "rt", MYNAME); +} + +#define SECTION_NONE 0 +#define SECTION_SYMBOL 1 +#define SECTION_PUNKTE 2 +#define SECTION_OVERLAY 3 + +#define MAXLINE 512 + +static struct _group { + int group; + char *name; + } *groups; +static int groups_cnt; + +void ovl_add_group(int aktgrp,char *akttxt) +{ + int i; + + i = 0; + while (irte_name); + i = 0; + while (irte_name = (char *) xrealloc(route->rte_name,(strlen(name)+1)*sizeof(char)); + strcpy(route->rte_name,name); +} + +void ovl_read(void) +{ + char line[MAXLINE]; + int isSection; + int aktTyp,aktCol,aktSize,aktArt,aktGroup; + int aktArea,aktWidth,aktHeight,aktTrans,aktTransByte,aktDir; + double aktX,aktY; + char *aktPath; + char *aktText; + char *pstr; + int keyw,i; + double rwert; + route_head *route_head = NULL; + waypoint *wpt; + int sym_cnt; + + groups = NULL; + groups_cnt = 0; + aktTyp = aktCol = aktSize = aktArt = aktGroup = -1; + aktArea = aktWidth = aktHeight = aktTrans = aktTransByte = aktDir = -1; + aktX = aktY = 0.0; + aktText = NULL; + aktPath = NULL; + sym_cnt = 0; + isSection = SECTION_NONE; + while (fgets(line,MAXLINE-1,fpin)!=NULL) + { + if( (pstr = strstr(line,"[Symbol "))!= NULL) + { + sym_cnt++; + isSection = SECTION_SYMBOL; + } + else if( (pstr = strstr(line,"[Overlay]"))!= NULL) + { + isSection = SECTION_OVERLAY; + } + else if (isSection==SECTION_SYMBOL) + { + pstr = strtok(line,"="); + if (pstr!=NULL) + { + keyw = isKeyword(pstr,Keywords); + pstr = strtok(NULL,"\n"); + if (pstr!=NULL) + { + switch(keyw) + { + case KEY_TYP : + aktTyp = atoi(pstr); + break; + case KEY_GROUP : + aktGroup = atoi(pstr); + ovl_add_group(aktGroup,"?"); /* 'Group' without relation to 'Text'-Symbol */ + switch(aktTyp) + { + case 3: // Linie + route_head = route_head_alloc(); + route_head->rte_num = sym_cnt; + route_head->rte_name = xstrdup(pstr); /* use group-number for the moment */ + route_add_head(route_head); + break; + } + break; + case KEY_COL : + aktCol = atoi(pstr); + break; + case KEY_ZOOM : + break; + case KEY_SIZE : + aktSize = atoi(pstr); + break; + case KEY_ART : + aktArt = atoi(pstr); + break; + case KEY_AREA : + aktArea = atoi(pstr); + if (aktTyp==5 || aktTyp==5 || aktTyp==7) isSection = SECTION_PUNKTE; // Rechteck, Kreis, Dreieck + break; + case KEY_PUNKTE : + isSection = SECTION_PUNKTE; // Linie, Fläche + break; +#ifdef WITH_BITMAP + case KEY_PATH : + aktPath = xstrdup(pstr); + isSection = SECTION_PUNKTE; // Bitmap + break; + case KEY_TRANS : + aktTrans = atoi(pstr); + break; + case KEY_TRANSBYTE : + aktTransByte = atoi(pstr); + break; +#endif + case KEY_TEXT : + aktText = xstrdup(pstr); + /* The last 'Text'-symbol wins as a information block for + waypoint/route description. + Infos from previous symbols get overwrited. + */ + ovl_add_group(aktGroup,aktText); + break; + case KEY_WIDTH : + aktWidth = atoi(pstr); + break; + case KEY_HEIGHT : + aktHeight = atoi(pstr); + break; + case KEY_DIR : + aktDir = atoi(pstr); + if (aktTyp==2) isSection = SECTION_PUNKTE; // Text + break; + } + } + } + } + else if (isSection==SECTION_PUNKTE) + { + pstr = strtok(line,"="); + if (strstr(pstr,"XKoord")!=NULL || strstr(pstr,"YKoord")!=NULL) + { + if ((pstr = strtok(NULL,"\n"))!=NULL) + { + rwert = atof(pstr); + if (line[0]=='X') + { + aktX = rwert; + } + else if (line[0]=='Y') + { + aktY = rwert; + switch(aktTyp) + { +#ifdef WITH_BITMAP + case 1: // Bitmap + wpt = waypt_new(); + wpt->latitude = aktY; + wpt->longitude = aktX; + wpt->altitude = 0.0; + wpt->shortname = strdup(aktPath); + waypt_add(wpt); + break; +#endif + case 2: // Text + isSection = SECTION_SYMBOL; + break; + case 3: // Linie + wpt = waypt_new(); + wpt->latitude = aktY; + wpt->longitude = aktX; + wpt->altitude = 0.0; + route_add_wpt(route_head, wpt); + break; + case 4: // Fläche + break; + case 5: // Rechteck + break; + case 6: // Kreis + break; + case 7: // Dreieck + break; + } + } + } + } + } + else if (isSection==SECTION_OVERLAY) + { + isSection = SECTION_NONE; + } + } + route_disp_all(route_add_name,NULL,NULL); + if (aktText!=NULL) xfree(aktText); + if (aktPath!=NULL) xfree(aktPath); + for (i=0;iargstring!=NULL) + { + if (strcmp(pstr,p->argstring)==0) + { + pstr = strtok(NULL,"\n"); + if (p->argtype==ARGTYPE_BOOL) + { + *(p->argval) = atoi(pstr) ? strdup(pstr) : NULL; + } + else + { + *(p->argval) = strdup(pstr); + } + break; + } + p++; + } + } + } + } + fclose(fpin); + } +} + +void ovl_wr_init(const char *fname) +{ + fpout = xfopen(fname, "wt", MYNAME); + govl_sum_n = 0.0; + govl_sum_e = 0.0; + govl_sumcnt = 0.0; + govl_symbol_cnt = 0; + + + ovl_read_parameter(govl_file_s!=NULL ? govl_file_s : PARAMETER_FILE); + + if (govl_col_s!=NULL) + { + govl_col = atoi(govl_col_s); + } + if (govl_size_s!=NULL) + { + govl_size = atoi(govl_size_s); + } + if (govl_mapname==NULL) + { + govl_mapname = xstrdup(MAPNAME); + } + if (govl_zoomfc_s!=NULL) + { + govl_zoomfc = atoi(govl_zoomfc_s); + } + if (govl_dimmfc_s!=NULL) + { + govl_dimmfc = atoi(govl_dimmfc_s); + } + if (govl_txtcol_s!=NULL) + { + govl_txtcol = atoi(govl_txtcol_s); + } + if (govl_txtsize_s!=NULL) + { + govl_txtsize = atoi(govl_txtsize_s); + } + if (govl_font_s!=NULL) + { + govl_font = atoi(govl_font_s); + } + if (govl_txttrans_s!=NULL) + { + govl_txttrans = 1; + } +} + +void ovl_wr_deinit(void) +{ + fprintf(fpout,"[Overlay]\n"); + fprintf(fpout,"Symbols=%d\n",govl_symbol_cnt); + fprintf(fpout,"[MapLage]\n"); + fprintf(fpout,"MapName=%s\n",govl_mapname); + fprintf(fpout,"DimmFc=%d\n",govl_dimmfc); + fprintf(fpout,"ZoomFc=%d\n",govl_zoomfc); + if (govl_symbol_cnt) + { + fprintf(fpout,"CenterLat=%.8lf\n",govl_sum_n/govl_sumcnt); // precision 8 = better than 1mm + fprintf(fpout,"CenterLong=%.8lf\n",govl_sum_e/govl_sumcnt); + } + else + { + fprintf(fpout,"CenterLong=10.52374295\n"); // Braunschweiger Löwe, Mittelpunkt der Welt :-) + fprintf(fpout,"CenterLat=52.26474445\n"); + } + fprintf(fpout,"RefOn=0\n"); + + fclose(fpout); +} + +void symbol_init(const route_head *hd) +{ + fprintf(fpout,"[Symbol %d]\n",govl_symbol_cnt+1); + fprintf(fpout,"Typ=3\n"); // Linie + fprintf(fpout,"Group=%d\n" ,govl_group_cnt+1+1); // group==1 : not a group + fprintf(fpout,"Col=%d\n" ,govl_col); + fprintf(fpout,"Zoom=2\n"); + fprintf(fpout,"Size=%d\n" ,govl_size); + fprintf(fpout,"Art=1\n"); + fprintf(fpout,"Punkte=%d\n" ,hd->rte_waypt_ct); + govl_cnt = 0; + govl_symbol_cnt++; + govl_group_cnt++; +} + +void symbol_text(double east,double north,char *text,int group) +{ + fprintf(fpout,"[Symbol %d]\n",govl_symbol_cnt+1); + fprintf(fpout,"Typ=2\n"); // Text + fprintf(fpout,"Group=%d\n",group+1); // group==1 : not a group + fprintf(fpout,"Col=%d\n",govl_txtcol); + fprintf(fpout,"Area=%d\n",govl_txttrans ? 1 : 2); // =2 opak =1 transparent + fprintf(fpout,"Zoom=%d\n",2); + fprintf(fpout,"Size=%d\n",govl_txtsize); + fprintf(fpout,"Font=%d\n",govl_font); + fprintf(fpout,"Dir=%d\n",100+((int) govl_dir)); + fprintf(fpout,"XKoord=%.8lf\n",east); // precision 8 = better than 1mm + fprintf(fpout,"YKoord=%.8lf\n",north); + fprintf(fpout,"Text=%s\n",text); + govl_symbol_cnt++; +} + +void symbol_point(const waypoint *wpt) +{ + double east,north; + + east = wpt->longitude; + north = wpt->latitude; + fprintf(fpout,"XKoord%d=%.8lf\n",govl_cnt,east); // precision 8 = better than 1mm + fprintf(fpout,"YKoord%d=%.8lf\n",govl_cnt,north); + govl_cnt++; + govl_sum_e += east; + govl_sum_n += north; + govl_sumcnt += 1.0; +/* + govl_last_east = east; + govl_last_north = north; +*/ +} + + +void symbol_deinit(const route_head *hd) +{ + queue *elem, *tmp; + waypoint *waypointp; + int i; + double lat1,lon1,lat2,lon2; + double lats,lons,late,lone; + double dist,d,dd; + + lat1 = lon1 = lat2 = lon2 = 0.0; + lats = lons = late = lone = 0.0; + dist = 0.0; + i = 0; + QUEUE_FOR_EACH(&(hd->waypoint_list), elem, tmp) + { + waypointp = (waypoint *) elem; + lat2 = waypointp->latitude *M_PI/180.0 ; + lon2 = waypointp->longitude*M_PI/180.0 ; + if (i) + { + d = gcdist(lat1, lon1, lat2, lon2 ); + dist += d; + } + else + { + lats = lat2; // start point + lons = lon2; + } + lat1 = lat2; + lon1 = lon2; + i++; + } + late = lat2; // end point + lone = lon2; + dd = 0; + i = 0; + elem = QUEUE_FIRST(&(hd->waypoint_list)); + while (elem!=&(hd->waypoint_list) && ddlatitude *M_PI/180.0; + lon2 = waypointp->longitude*M_PI/180.0; + if (i) + { + d = gcdist(lat1, lon1, lat2, lon2 ); + dd += d; + } + lat1 = lat2; + lon1 = lon2; + elem = QUEUE_NEXT(elem); + i++; + } + + d = gcdist(lats,lons,late,lone); +// d = acos( sin(lats)*sin(late)+cos(lats)*cos(late)*cos(lone-lons) ); + dd = acos( (sin(late) - sin(lats)*cos(d))/(cos(lats)*sin(d)) ); + if (lone 360.0 ? dd - 360.0 : dd; // normalizing + + /* name of route */ + /* plot text at the last point of route */ + govl_dir = dd; // approximated text rotation, correct value must be the azimuth in UTM + symbol_text(lon1*180.0/M_PI,lat1*180.0/M_PI,hd->rte_name,govl_group_cnt); + govl_dir = 0.0; // restore +} + +static void overlay_waypt_pr(const waypoint *waypointp) +{ + const char *oname; + char *odesc; + + /* + * Desparation time, try very hard to get a good shortname + */ + odesc = waypointp->notes; + if (!odesc) { + odesc = waypointp->description; + } + if (!odesc) { + odesc = waypointp->shortname; + } + oname = global_opts.synthesize_shortnames ? + mkshort(mkshort_handle, odesc) : + waypointp->shortname; + + fprintf(fpout,"[Symbol %d]\n",govl_symbol_cnt+1); + fprintf(fpout,"Typ=1\n"); + fprintf(fpout,"Group=1\n"); + fprintf(fpout,"Width=100\n"); + fprintf(fpout,"Height=100\n"); + fprintf(fpout,"Dir=%d\n",100+((int) govl_dir)); + fprintf(fpout,"Zoom=2\n"); + fprintf(fpout,"Trans=2\n"); + fprintf(fpout,"TransByte=5\n"); + fprintf(fpout,"Path=%s\n","waypoint.bmp"); + fprintf(fpout,"XKoord=%.8lf\n",waypointp->longitude); + fprintf(fpout,"YKoord=%.8lf\n",waypointp->latitude); + govl_symbol_cnt++; + govl_sum_e += waypointp->longitude; + govl_sum_n += waypointp->latitude; + govl_sumcnt += 1.0; + +} + +void ovl_write(void) +{ + waypt_disp_all(overlay_waypt_pr); + track_disp_all(symbol_init, symbol_deinit, symbol_point); + route_disp_all(symbol_init, symbol_deinit, symbol_point); +/* + switch(global_opts.objective) + { + case wptdata: + break; + case trkdata: + break; + } +*/ +} + + +ff_vecs_t overlay_vecs = { + ff_type_internal, + FF_CAP_RW_ALL, + ovl_rd_init, + ovl_wr_init, + ovl_rd_deinit, + ovl_wr_deinit, + ovl_read, + ovl_write, + NULL, + ovl_args +}; diff --git a/ozi.c b/ozi.c index ff9487571..b655f61a2 100644 --- a/ozi.c +++ b/ozi.c @@ -4,7 +4,7 @@ As described in OziExplorer Help File - Copyright (C) 2002 Robert Lipe, robertlipe@usa.net + Copyright (C) 2002-2005 Robert Lipe, robertlipe@usa.net This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -548,6 +548,13 @@ data_read(void) ozi_objective = wptdata; } } + + if (linecount == 2) { + if (case_ignore_strncmp(buff, "WGS 84", 6)) { + warning(MYNAME "Only supports reading WGS 84 datum, not '%s'\n", buff); + } + } + if ((strlen(buff)) && (strstr(buff, ",") != NULL)) { wpt_tmp = waypt_new(); @@ -626,7 +633,7 @@ ozi_waypt_pr(const waypoint * wpt) if ((!wpt->shortname) || (global_opts.synthesize_shortnames)) { if (wpt->description) { if (global_opts.synthesize_shortnames) - shortname = mkshort(mkshort_handle, wpt->description); + shortname = mkshort_from_wpt(mkshort_handle, wpt); else shortname = csv_stringclean(wpt->description, ","); } else { @@ -692,6 +699,7 @@ data_write(void) ff_vecs_t ozi_vecs = { ff_type_file, + FF_CAP_RW_ALL, rd_init, wr_init, rd_deinit, diff --git a/palmdoc.c b/palmdoc.c index 40cf79b00..5e82f5aea 100644 --- a/palmdoc.c +++ b/palmdoc.c @@ -256,7 +256,8 @@ static void write_header( void ) { --recs; } - opdb_rec = new_Record (0, 0, 0, sizeof(struct doc_record0)+sizeof(short)*(ct-1), (const ubyte *)rec0); + opdb_rec = new_Record (0, 0, 0, + (uword) (sizeof(struct doc_record0)+sizeof(short)*(ct-1)), (const ubyte *)rec0); if (opdb_rec == NULL) { fatal(MYNAME ": libpdb couldn't create summary record\n"); @@ -265,6 +266,7 @@ static void write_header( void ) { if (pdb_InsertRecord(opdb, NULL, opdb_rec)) { fatal(MYNAME ": libpdb couldn't insert summary record\n"); } + xfree(rec0); } static void write_bookmarks( void ) { @@ -302,7 +304,6 @@ static void write_bookmarks( void ) { fatal(MYNAME ": libpdb couldn't append bookmark record\n"); } - xfree( oldmark ); } } @@ -316,7 +317,7 @@ static void commit_buffer( void ) { compress( &buf ); - opdb_rec = new_Record (0, 0, ct++, buf.len, (const ubyte *)buf.data); + opdb_rec = new_Record (0, 0, ct++, (uword) buf.len, (const ubyte *)buf.data); if (opdb_rec == NULL) { fatal(MYNAME ": libpdb couldn't create record\n"); @@ -414,26 +415,30 @@ palmdoc_disp(const waypoint *wpt) int latint, lonint; char tbuf[1024]; time_t tm = wpt->creation_time; - long utmz; + int32 utmz; double utme, utmn; char utmzc; + char *bm; char bookmarktext[17]; if ( bmid ) { + char * s = mkshort_from_wpt(mkshort_bookmark_handle, wpt); sprintf( bookmarktext, "%6s:%9s", - wpt->shortname?wpt->shortname:"", - mkshort(mkshort_bookmark_handle, wpt->description)); + wpt->shortname?wpt->shortname:"",s); + xfree(s); } else { - sprintf( bookmarktext, "%16s", - mkshort(mkshort_bookmark_handle, wpt->description)); + char * s = mkshort_from_wpt(mkshort_bookmark_handle, wpt); + sprintf( bookmarktext, "%16s", s); + xfree(s); } - - create_bookmark(xstrdup(bookmarktext)); + + bm = xstrdup(bookmarktext); + create_bookmark(bm); - lonint = abs(wpt->longitude); - latint = abs(wpt->latitude); + lonint = abs((int) wpt->longitude); + latint = abs((int) wpt->latitude); GPS_Math_WGS84_To_UTM_EN(wpt->latitude, wpt->longitude, &utme, &utmn, &utmz, &utmzc); @@ -443,7 +448,7 @@ palmdoc_disp(const waypoint *wpt) strftime(tbuf, sizeof(tbuf), "%d-%b-%Y", localtime(&tm)); docprintf(300, "%-16s %c%d %06.3f %c%d %06.3f (%ld%c %6.0f %7.0f)", - (global_opts.synthesize_shortnames) ? mkshort(mkshort_handle, wpt->description) : wpt->shortname, + (global_opts.synthesize_shortnames) ? mkshort_from_wpt(mkshort_handle, wpt) : wpt->shortname, wpt->latitude < 0 ? 'S' : 'N', abs(latint), 60.0 * (fabs(wpt->latitude) - latint), wpt->longitude < 0 ? 'W' : 'E', abs(lonint), 60.0 * (fabs(wpt->longitude) - lonint), utmz, utmzc, utme, utmn); @@ -604,6 +609,7 @@ data_write(void) ff_vecs_t palmdoc_vecs = { ff_type_file, + { ff_cap_write, ff_cap_none, ff_cap_none}, NULL, wr_init, NULL, diff --git a/pathaway.c b/pathaway.c new file mode 100644 index 000000000..e3af37279 --- /dev/null +++ b/pathaway.c @@ -0,0 +1,631 @@ +/* + Support for PathAway Palm Database, + Copyright (C) 2005 Olaf Klein, o.b.klein@t-online.de + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + +*/ + +/* ToDo: + --- date format for read database -- +*/ + +#include "defs.h" +#include "coldsync/palm.h" +#include "coldsync/pdb.h" +#include "csv_util.h" + +#define MYNAME "PathAway pdb" + +#define PPDB_MAGIC_TRK 0x55735472 /* UsTr */ +#define PPDB_MAGIC_WPT 0x506f4c69 /* PoLi */ +#define PPDB_MAGIC 0x4b6e5772 /* KwNr */ + +FILE *fd_in, *fd_out; +struct pdb *pdb_in, *pdb_out; +char *fname_in, *fname_out; +static gpsdata_type ppdb_type; + +typedef struct ppdb_appdata +{ + unsigned char reservedA[274]; /* all 0 */ + unsigned char dirtyFlag; + unsigned char dataBaseSubType; /* 0 = Track, 1 = Route */ + short int dbAttributes; /* 0 */ + char vehicleStr[100]; + unsigned char reservedB[100]; /* all 0 */ +} ppdb_appdata_t; + +#define PPDB_APPINFO_SIZE sizeof(struct ppdb_appdata) + +static char *date_fmt = NULL; +static char *dbname = NULL; +static char *deficon = NULL; + +static arglist_t ppdb_args[] = +{ + {"dbname", &dbname, "Database name", NULL, ARGTYPE_STRING}, + {"deficon", &deficon, "Default icon name", NULL, ARGTYPE_STRING}, +/* {"dtfmt", &date_fmt, "Date format", NULL, ARGTYPE_STRING }, ToDo */ + {0, 0, 0, 0 } +}; + +static void +is_fatal(int is, const char *msg, ... ) +{ + if (is) fatal(MYNAME ": %s\n", msg); +} + +#define CHECK_INP(i, j) is_fatal((i != j), "Error in data structure.") + +/* + * utilities + */ + +char *ppdb_strcat(char *dest, char *src, char *def, int *size) +{ + int len; + char *res, *tmp; + + tmp = src; + if (tmp == NULL) + { + tmp = def; + if (tmp == NULL) return dest; + } + if (*tmp == '\0') return dest; + + len = strlen(dest) + strlen(tmp) + 1; + if (len > *size) + { + *size = len; + res = xrealloc(dest, *size); + } + else + res = dest; + strcat(res, tmp); + return res; +} + +#define STR_POOL_SIZE 16 /* !!! any power of 2 !!! */ + +static char *str_pool[STR_POOL_SIZE] = {}; +static size_t str_pool_s[STR_POOL_SIZE] = {}; +static int str_poolp = -1; + +void str_pool_init(void) +{ + int i; + for (i = 0; i < STR_POOL_SIZE; i++) + { + str_pool[i] = NULL; + str_pool_s[i] = 0; + } +} + +void str_pool_deinit(void) +{ + int i; + + for (i = 0; i < STR_POOL_SIZE; i++) + if ( str_pool_s[i] != 0 ) + { + xfree(str_pool[i]); + str_pool[i] = NULL; + str_pool_s[i] = 0; + } +} + +char *str_pool_get(size_t size) +{ + char *tmp; + + str_poolp = ((str_poolp + 1) & (STR_POOL_SIZE - 1)); + tmp = str_pool[str_poolp]; + + if (str_pool_s[str_poolp] == 0) + tmp = xmalloc(size); + else if (str_pool_s[str_poolp] < size) + tmp = xrealloc(tmp, size); + else + return tmp; + + str_pool[str_poolp] = tmp; + str_pool_s[str_poolp] = size; + + return tmp; +} + +char *str_pool_getcpy(char *src, char *def) +{ + char *res; + + if (src == NULL) + { + src = def; + if (src == NULL) src = ""; + } + res = str_pool_get(strlen(src) + 1); + strcpy(res, src); + + return res; +} + +/* + * decoding/formatting functions + */ + +char *ppdb_fmt_float(const double val) +{ + char *c; + char *str = str_pool_get(32); + snprintf(str, 32, "%.8f", val); + c = str + strlen(str) - 1; + while ((c > str) && (*c == '0')) + { + *c = '\0'; + c--; + if (*c == '.') + { + c++; + *c = '0'; + break; + } + } + return str; +} + +char *ppdb_fmt_degrees(char dir, double val) +{ + char *tmp; + char *str = str_pool_get(32); + int deg = abs(val); + double min = 60.0 * (fabs(val) - deg); + int power = 0; + double fx = min; + while (fx > 1.0) + { + fx = fx / 10.0; + power++; + } + snprintf(str, 31, "%c%02d 000", dir, deg); + snprintf(str + 6 - power, 24, "%.8f", min); + + tmp = str + strlen(str) - 1; /* trim trailing nulls */ + while ((tmp > str) && (*tmp == '0')) + { + *tmp = '\0'; + tmp--; + if (*tmp == '.') + { + tmp++; + *tmp = '0'; + break; + } + } + return str; +} + +double ppdb_decode_coord(const char *str) +{ + double val; + int deg; + char dir; + + if (*str < 'A') /* only numeric */ + { + CHECK_INP(1, sscanf(str,"%lf", &val)); + return val; + } + else + { + char *tmp = strchr(str, ' '); + if ((tmp) && (tmp - str < 4)) + { + CHECK_INP(3, sscanf(str,"%c%d %lf", &dir, °, &val)); + val = deg + (val / 60.0); + } + else + { + CHECK_INP(2, sscanf(str,"%c%lf", &dir, &val)); + } + if ((dir == 'S') || (dir == 'W')) + val = -val; + } + return val; +} + +int ppdb_decode_tm(char *str, struct tm *tm) +{ + int i = 3; + int msec, d1, d2, d3, d4, year; + time_t tnow; + struct tm now; + + if (*str == '\0') return 0; /* empty date and time */ + + if (strchr(str, '.')) /* time in hhmmss.ms */ + { + CHECK_INP(8, sscanf(str, "%02d%02d%02d.%d %02d%02d%02d%02d", + &tm->tm_hour, &tm->tm_min, &tm->tm_sec, + &msec, &d1, &d2, &d3, &d4)); + } + else + { + CHECK_INP(7, sscanf(str, "%02d%02d%02d %02d%02d%02d%02d", + &tm->tm_hour, &tm->tm_min, &tm->tm_sec, + &d1, &d2, &d3, &d4)); + } + + tnow = current_time(); + now = *localtime(&tnow); + now.tm_year += 1900; + now.tm_mon++; + + year = (d1 * 100) + d2; + + /* next code works for most, except for 19. and 20. of month */ + /* for trouble use input date format - !!! ToDo !!! */ + + if ((year < 1980) || (year > now.tm_year)) /* YYYYMMDD or DDMMYYY ????? */ + { + tm->tm_year = (d3 * 100) + d4; + tm->tm_mon = d2; + tm->tm_mday = d1; + } + else + { + tm->tm_year = (d1 * 100) + d2; + tm->tm_mon = d3; + tm->tm_mday = d4; + } + + return 1; +} + +static int ppdb_read_wpt(const struct pdb *pdb_in, const struct pdb_record *pdb_rec, route_head *head) +{ + char *data, *str, *tmp; + char latdir, longdir; + int latdeg, longdeg, i; + double latval, longval, altfeet; + struct tm tm; + + for (pdb_rec = pdb_in->rec_index.rec; pdb_rec; pdb_rec=pdb_rec->next) + { + int line = 0; + waypoint *wpt_tmp = waypt_new(); + data = (char *) pdb_rec->data; + + str = csv_lineparse(data, ",", """", line++); + while (str != NULL) + { + switch(line) + { + case 1: + wpt_tmp->latitude = ppdb_decode_coord(str); + break; + case 2: + wpt_tmp->longitude = ppdb_decode_coord(str); + break; + case 3: + if (*str != '\0') + { + CHECK_INP(1, sscanf(str, "%lf", &altfeet)); + if (altfeet != -9999) + wpt_tmp->altitude = altfeet / 3.2808; + } + break; + case 4: + memset(&tm, 0, sizeof(tm)); + if (ppdb_decode_tm(str, &tm)) + { + tm.tm_year -= 1900; + tm.tm_mon--; + wpt_tmp->creation_time = mktime(&tm) + get_tz_offset(); + } + break; + case 5: + if (*str != '\0') + wpt_tmp->shortname = xstrdup(str); + break; + case 6: /* icon, ignore */ + break; + case 7: + if (*str != '\0') + wpt_tmp->notes = xstrdup(str); + break; + + } + str = csv_lineparse(NULL, ",", """", line++); + } + + if (head) + route_add_wpt(head, wpt_tmp); + else + waypt_add(wpt_tmp); + + } + return 0; +} + +/* ============================================================================================ + * &&& gobal callbacks &&& + * ----------------------------------------------------------------------------------------- */ + +static void ppdb_rd_init(const char *fname) +{ + fname_in = xstrdup(fname); + str_pool_init(); + fd_in = xfopen(fname, "rb", MYNAME); + +} + +static void ppdb_rd_deinit(void) +{ + fclose(fd_in); + str_pool_deinit(); + xfree(fname_in); +} + +static void ppdb_read(void) +{ + struct pdb_record *pdb_rec; + ppdb_appdata_t *info = NULL; + route_head *track_head, *route_head; + const char *descr = NULL; + + if (NULL == (pdb_in = pdb_Read(fileno(fd_in)))) + fatal(MYNAME ": pdb_Read failed.\n"); + + if (pdb_in->creator != PPDB_MAGIC) /* identify the database */ + fatal(MYNAME ": Not a PathAway pdb file.\n"); + + if (pdb_in->version != 3) /* Currently we support only version 3 */ + fatal(MYNAME ": This file is from an untested version (%d) of PathAway and is unsupported.\n", pdb_in->version); + + if ((pdb_in->appinfo_len > 0) && (pdb_in->appinfo != NULL)) + { + info = (ppdb_appdata_t *) pdb_in->appinfo; + descr = info->vehicleStr; + } + + switch(pdb_in->type) + { + case PPDB_MAGIC_TRK: + ppdb_type = trkdata; /* as default */ + if (info) + { + switch(info->dataBaseSubType) + { + case 0: + ppdb_type = trkdata; + break; + case 1: + ppdb_type = rtedata; + break; + default: + fatal(MYNAME": Invalid database subtype.\n"); + } + } + break; + + case PPDB_MAGIC_WPT: + ppdb_type = wptdata; + break; + + default: + fatal(MYNAME ": It looks like a PathAway pdb, but has no gps magic.\n"); + } + + switch(ppdb_type) + { + case trkdata: + track_head = route_head_alloc(); + track_add_head(track_head); + track_head->rte_name = xstrdup(pdb_in->name); + ppdb_read_wpt(pdb_in, pdb_rec, track_head); + break; + case rtedata: + route_head = route_head_alloc(); + route_add_head(route_head); + route_head->rte_name = xstrdup(pdb_in->name); + ppdb_read_wpt(pdb_in, pdb_rec, route_head); + break; + case wptdata: + ppdb_read_wpt(pdb_in, pdb_rec, NULL); + break; + } + + free_pdb(pdb_in); +} + +/* ============================================================================================ + * PPDB: Write support + * -------------------------------------------------------------------------------------------*/ + +static void ppdb_wr_init(const char *fname) +{ + fname_out = xstrdup(fname); + str_pool_init(); + fd_out = xfopen(fname, "wb", MYNAME); +} + +static void ppdb_wr_deinit(void) +{ + fclose(fd_out); + str_pool_deinit(); + xfree(fname_out); +} + +/* + * ppdb_write_wpt: callback for waypoint output + */ + +#define REC_SIZE 128 + +static void ppdb_write_wpt(const waypoint *wpt) +{ + char *buff, *tmp; + char latdir, longdir; + int latdeg, longdeg, len; + struct pdb_record *rec; + static int ct; + struct tm tm; + + buff = xmalloc(REC_SIZE); + memset(buff, 0, REC_SIZE); + + if (wpt->latitude < 0) + latdir = 'S'; + else + latdir = 'N'; + if (wpt->longitude < 0) + longdir = 'W'; + else + longdir = 'E'; + + snprintf(buff, REC_SIZE, "%s,%s,", + ppdb_fmt_degrees(latdir, wpt->latitude), + ppdb_fmt_degrees(longdir, wpt->longitude) + ); + + len = REC_SIZE; /* we have coordinates in buff, now optional stuff */ + + if (fabs(wpt->altitude) < 9999.0) + { + tmp = str_pool_get(32); + snprintf(tmp, 32, ppdb_fmt_float(wpt->altitude * 3.2808)); + buff = ppdb_strcat(buff, tmp, NULL, &len); + } + buff = ppdb_strcat(buff, ",", NULL, &len); + if ( wpt->creation_time != 0) + { + tmp = str_pool_get(20); + tm = *gmtime(&wpt->creation_time); + strftime(tmp, 20, "%H%M%S %Y%m%d", &tm); + buff = ppdb_strcat(buff, tmp, NULL, &len); + } + buff = ppdb_strcat(buff, ",", NULL, &len); + + tmp = str_pool_getcpy(wpt->shortname, ""); + while (strchr(tmp, ',') != NULL) + *strchr(tmp, ',') = '.'; + buff = ppdb_strcat(buff, tmp, "", &len); + + buff = ppdb_strcat(buff, ",", NULL, &len); + buff = ppdb_strcat(buff, deficon, "0", &len); + buff = ppdb_strcat(buff, ",", NULL, &len); + + tmp = str_pool_getcpy(wpt->description, ""); + if (strchr(tmp, ',') != NULL ) + { + buff = ppdb_strcat(buff, "\"", NULL, &len); + while (strchr(tmp, '"') != NULL) + *strchr(tmp, '"') = '\''; + buff = ppdb_strcat(buff, tmp, NULL, &len); + buff = ppdb_strcat(buff, "\"", NULL, &len); + } + else + buff = ppdb_strcat(buff, tmp, "", &len); + + len = strlen(buff) + 1; + rec = new_Record(0, 0, ct++, len, (const ubyte *) buff); + + if (rec == NULL) + fatal(MYNAME ": libpdb couldn't create record\n"); + + if (pdb_AppendRecord(pdb_out, rec)) + fatal(MYNAME ": libpdb couldn't append record\n"); + + xfree(buff); +} + +/* + * track and route write callbacks + */ + +static void ppdb_track_header(const route_head *rte) +{ +} + +static void ppdb_track_trailer(const route_head *rte) +{ +} + + +static void ppdb_write(void) +{ + ppdb_appdata_t *appinfo = NULL; + + if (NULL == (pdb_out = new_pdb())) + fatal(MYNAME ": new_pdb failed\n"); + if (dbname) + strncpy(pdb_out->name, dbname, PDB_DBNAMELEN); + + pdb_out->name[PDB_DBNAMELEN-1] = 0; + pdb_out->attributes = PDB_ATTR_BACKUP; + pdb_out->ctime = pdb_out->mtime = current_time() + 2082844800U; + pdb_out->creator = PPDB_MAGIC; + pdb_out->version = 3; + + if (global_opts.objective != wptdata) /* Waypoint target do not need appinfo block */ + { + appinfo = xmalloc(PPDB_APPINFO_SIZE); + memset(appinfo, 0, PPDB_APPINFO_SIZE); + + pdb_out->appinfo = (void *)appinfo; + pdb_out->appinfo_len = PPDB_APPINFO_SIZE; + } + + switch(global_opts.objective) /* Only one target is possible */ + { + case wptdata: + if (dbname == NULL) strncpy(pdb_out->name, "PathAway Waypoints", PDB_DBNAMELEN); + pdb_out->type = PPDB_MAGIC_WPT; + waypt_disp_all(ppdb_write_wpt); + break; + case trkdata: + if (dbname == NULL) strncpy(pdb_out->name, "PathAway Track", PDB_DBNAMELEN); + pdb_out->type = PPDB_MAGIC_TRK; + appinfo->dataBaseSubType = 0; + track_disp_all(ppdb_track_header, ppdb_track_trailer, ppdb_write_wpt); + break; + case rtedata: + if (dbname == NULL) strncpy(pdb_out->name, "PathAway Route", PDB_DBNAMELEN); + pdb_out->type = PPDB_MAGIC_TRK; + appinfo->dataBaseSubType = 1; + route_disp_all(ppdb_track_header, ppdb_track_trailer, ppdb_write_wpt); + break; + } + + pdb_Write(pdb_out, fileno(fd_out)); + + if (appinfo != NULL) xfree(appinfo); +} + + +ff_vecs_t ppdb_vecs = { + ff_type_file, + FF_CAP_RW_ALL, + ppdb_rd_init, + ppdb_wr_init, + ppdb_rd_deinit, + ppdb_wr_deinit, + ppdb_read, + ppdb_write, + NULL, + ppdb_args +}; diff --git a/pcx.c b/pcx.c index 4b4997b6d..fb4f87276 100644 --- a/pcx.c +++ b/pcx.c @@ -94,7 +94,7 @@ data_read(void) &symnum); desc[sizeof(desc)-1] = '\0'; name[sizeof(name)-1] = '\0'; - wpt_tmp = xcalloc(sizeof(*wpt_tmp), 1); + wpt_tmp = waypt_new(); wpt_tmp->altitude = alt; wpt_tmp->shortname = xstrdup(name); wpt_tmp->description = xstrdup(desc); @@ -194,7 +194,7 @@ gpsutil_disp(const waypoint *wpt) fprintf(file_out, "W %-6.6s %c%08.5f %c%011.5f %s %5d %-40.40s %5e %d\n", global_opts.synthesize_shortnames ? - mkshort(mkshort_handle, wpt->description) : + mkshort_from_wpt(mkshort_handle, wpt) : wpt->shortname, lat < 0.0 ? 'S' : 'N', fabs(lat), @@ -266,6 +266,7 @@ fprintf(file_out, ff_vecs_t pcx_vecs = { ff_type_file, + { ff_cap_read | ff_cap_write, ff_cap_read | ff_cap_write, ff_cap_none }, rd_init, wr_init, rd_deinit, diff --git a/position.c b/position.c index 9105dfff0..2df410826 100644 --- a/position.c +++ b/position.c @@ -35,6 +35,8 @@ static char *latopt = NULL; static char *lonopt = NULL; static char *exclopt = NULL; static char *nosort = NULL; +static char *maxctarg = NULL; +static int maxct; waypoint * home_pos; @@ -64,6 +66,8 @@ arglist_t radius_args[] = { NULL, ARGTYPE_BOOL }, {"nosort", &nosort, "Inhibit sort by distance to center.", NULL, ARGTYPE_BOOL }, + {"maxcount", &maxctarg,"Output no more than this number of points", + NULL, ARGTYPE_INT }, {0, 0, 0, 0, 0} }; @@ -221,18 +225,24 @@ position_process_route(const route_head * rh) { } static void -position_noop(){ +position_noop_w(const waypoint *w) +{ } -void position_process() +static void +position_noop_t(const route_head *h) +{ +} + +void position_process(void) { int i = waypt_count(); if (i) position_runqueue(&waypt_head, i, wptdata); - route_disp_all(position_process_route, position_noop, position_noop); - track_disp_all(position_process_route, position_noop, position_noop); + route_disp_all(position_process_route, position_noop_t, position_noop_w); + track_disp_all(position_process_route, position_noop_t, position_noop_w); } void @@ -319,8 +329,14 @@ radius_process(void) */ for (i = 0; i < wc; i++) { waypoint * wp = comp[i]; - waypt_add(wp); + xfree(wp->extra_data); + wp->extra_data = NULL; + + if (maxctarg && i >= maxct) { + continue; + } + waypt_add(wp); } xfree(comp); @@ -341,6 +357,12 @@ radius_init(const char *args) { } } + if (maxctarg) { + maxct = atoi(maxctarg); + } else { + maxct = 0; + } + home_pos = (waypoint *) xcalloc(sizeof(*home_pos), 1); if (latopt) diff --git a/psitrex.c b/psitrex.c index 9166f830f..89ab8dd9a 100644 --- a/psitrex.c +++ b/psitrex.c @@ -208,7 +208,6 @@ static void psit_getToken(FILE *psit_file, char *buf, size_t sz, psit_tokenSep_type delimType) { int c; -char *buf2 = buf; /* MRCB debug */ *buf = 0; @@ -285,8 +284,6 @@ psit_waypoint_r(FILE *psit_file, waypoint **wpt) int garmin_icon_num; waypoint *thisWaypoint; - double psit_altitude = unknown_alt; - double psit_depth = unknown_alt; if (strlen(psit_current_token) > 0) { thisWaypoint = waypt_new(); @@ -331,10 +328,8 @@ static void psit_waypoint_w(FILE *psit_file, const waypoint *wpt) { int icon; - char *src; - const char *ident; - int display = 1; - int colour = 0; /* (unknown colour) black is 1, white is 16 */ + const char *ident; + char *src = 0; /* BUGBUG Passed to mkshort */ fprintf(psit_file, "%11.6f,%11.6f,", wpt->latitude, @@ -383,13 +378,10 @@ psit_route_r(FILE *psit_file, route_head **rte) int garmin_icon_num; - time_t dateTime = 0; route_head *rte_head; unsigned int rte_count; waypoint *thisWaypoint; - double psit_altitude = unknown_alt; - double psit_depth = unknown_alt; psit_getToken(psit_file,psit_current_token,sizeof(psit_current_token), ltrimEOL); @@ -525,8 +517,6 @@ psit_track_r(FILE *psit_file, route_head **trk) unsigned int trk_count; waypoint *thisWaypoint; - double psit_altitude = unknown_alt; - double psit_depth = unknown_alt; psit_getToken(psit_file,psit_current_token,sizeof(psit_current_token), ltrimEOL); if (strlen(psit_current_token) == 0) { @@ -676,10 +666,6 @@ psit_trackdatapoint_w(FILE *psit_file, const waypoint *wpt) time_t t = wpt->creation_time; struct tm *tmTime = gmtime(&t); - double psit_altitude = wpt->altitude; - double psit_proximity = unknown_alt; - double psit_depth = unknown_alt; - fprintf(psit_file, "%11.6f,%11.6f,", wpt->latitude, wpt->longitude); @@ -799,6 +785,7 @@ psit_write(void) ff_vecs_t psit_vecs = { ff_type_file, + FF_CAP_RW_ALL, psit_rd_init, psit_wr_init, psit_rd_deinit, diff --git a/psp.c b/psp.c index 01fde6645..b3a04e650 100644 --- a/psp.c +++ b/psp.c @@ -158,7 +158,7 @@ buffer_washer(char * buff, int buffer_len) for (i = 0 ; i < buffer_len - 1; i++) { if (buff[i] == '\0') { - memcpy(&buff[i], &buff[i+1], buffer_len - i); + memmove(&buff[i], &buff[i+1], buffer_len - i); buffer_len--; buff[buffer_len] = '\0'; } @@ -215,7 +215,7 @@ psp_read(void) pincount = le_read16(&buff[12]); while (pincount--) { - wpt_tmp = xcalloc(sizeof(*wpt_tmp),1); + wpt_tmp = waypt_new(); wpt_tmp->altitude = unknown_alt; @@ -327,7 +327,7 @@ psp_waypt_pr(const waypoint *wpt) if ((! wpt->shortname) || (global_opts.synthesize_shortnames)) { if (wpt->description) { if (global_opts.synthesize_shortnames) - shortname = mkshort(mkshort_handle, wpt->description); + shortname = mkshort_from_wpt(mkshort_handle, wpt); else shortname = xstrdup(wpt->description); } else { @@ -459,6 +459,7 @@ psp_write(void) ff_vecs_t psp_vecs = { ff_type_file, + FF_CAP_RW_WPT, psp_rd_init, psp_wr_init, psp_rd_deinit, diff --git a/queue.h b/queue.h index 2cbb72748..e042e235e 100644 --- a/queue.h +++ b/queue.h @@ -33,10 +33,15 @@ queue * dequeue(queue *element); #define QUEUE_LAST(head) (head)->prev #define QUEUE_EMPTY (head)->next == head #define QUEUE_MOVE(newhead,oldhead) \ - (newhead)->next = (oldhead)->next; \ - (newhead)->prev = (oldhead)->prev; \ - (newhead)->next->prev = (newhead); \ - (newhead)->prev->next = (newhead); \ + if ( (oldhead)->next == (oldhead) ) {\ + (newhead)->next = (newhead)->prev = (newhead); \ + } \ + else { \ + (newhead)->next = (oldhead)->next; \ + (newhead)->prev = (oldhead)->prev; \ + (newhead)->next->prev = (newhead); \ + (newhead)->prev->next = (newhead); \ + } \ (oldhead)->next = (oldhead)->prev = (oldhead) #define ENQUEUE_TAIL(listhead, element) \ diff --git a/quovadis.c b/quovadis.c index a5274f801..e71eda892 100644 --- a/quovadis.c +++ b/quovadis.c @@ -173,9 +173,9 @@ quovadis_writewpt(waypoint *wpt) rec = (struct record *) xcalloc(sizeof(*rec),1); - be_write32(&rec->longitude, (wpt->longitude + - 180.0) * 1000000.0); - be_write32(&rec->latitude, (90.0 - wpt->latitude) * 1000000.0); + be_write32(&rec->longitude, (unsigned int) ((wpt->longitude + + 180.0) * 1000000.0)); + be_write32(&rec->latitude, (unsigned int) ((90.0 - wpt->latitude) * 1000000.0)); if ( wpt->shortname ) { strncpy(rec->name, wpt->shortname, 32 ); rec->name[31] = '\0'; @@ -265,8 +265,8 @@ data_write(void) if (rec_index != 0) { struct pdb_record* pdb_rec; - pdb_rec = new_Record(0, 0, ct++, rec_index * - sizeof(struct record), current_rec); + pdb_rec = new_Record(0, 0, ct++, (uword) (rec_index * + sizeof(struct record)), current_rec); if (pdb_rec == NULL) { fatal(MYNAME ": libpdb couldn't create record\n"); @@ -285,6 +285,7 @@ data_write(void) ff_vecs_t quovadis_vecs = { ff_type_file, + FF_CAP_RW_WPT, rd_init, wr_init, rd_deinit, diff --git a/reference/Glad_5.exp b/reference/Glad_5.exp index 458090147..f2397b966 100644 --- a/reference/Glad_5.exp +++ b/reference/Glad_5.exp @@ -6,531 +6,531 @@ 0 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMEdward Islandlegnum0usrmrkEdward Islandselect2 - attr=grpnamROUTENAME + + 1 -20.226667 149.205000 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMScawfell Islandlegnum1usrmrkScawfell Islandselect2 - attr=grpnamROUTENAME + + 1 - -20.850001 - 149.641668 + -20.850000 + 149.641667 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMMiddle Islandlegnum2usrmrkMiddle Islandselect2 - attr=grpnamROUTENAME + + 1 -21.680097 150.176053 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMClara Grouplegnum3usrmrkClara Groupselect2 - attr=grpnamROUTENAME + + 1 -22.318424 - 150.747717 + 150.747716 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMCape Capricornlegnum4usrmrkCape Capricornselect2 - attr=grpnamROUTENAME + + 1 - -23.448418 - 151.322717 + -23.448417 + 151.322716 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMGladstone FWBlegnum5usrmrkGladstone FWBselect2 - attr=grpnamROUTENAME + + 1 - -23.890915 - 151.516051 + -23.890914 + 151.516050 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMHigh Peaklegnum6usrmrkHigh Peakselect2 - attr=grpnamROUTENAME + + 1 - -21.951660 - 150.754997 + -21.951659 + 150.754996 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMPenrith Islandlegnum7usrmrkPenrith Islandselect2 - attr=grpnamROUTENAME + + 1 - -20.988435 - 149.929386 + -20.988434 + 149.929385 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMPinnacle Pointlegnum8usrmrkPinnacle Pointselect2 - attr=grpnamROUTENAME + + 1 - -20.081094 - 149.064391 + -20.081093 + 149.064390 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMTink Shoallegnum9usrmrkTink Shoalselect2 - attr=grpnamROUTENAME + + 1 -19.375083 - 147.819368 + 147.819367 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMPeloruslegnum10usrmrkPelorusselect2 - attr=grpnamROUTENAME + + 1 -18.433464 - 146.549414 + 146.549413 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMEva Islandlegnum11usrmrkEva Islandselect2 - attr=grpnamROUTENAME + + 1 -18.213466 - 146.409415 + 146.409414 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMLittle Fitzroy Islandlegnum12usrmrkLittle Fitzroy Islandselect2 - attr=grpnamROUTENAME + + 1 -16.913473 - 146.059411 + 146.059410 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMCairns FWBlegnum13usrmrkCairns FWBselect2 - attr=grpnamROUTENAME + + 1 - -16.731976 + -16.731975 145.889412 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMLow Isleslegnum14usrmrkLow Islesselect2 - attr=grpnamROUTENAME + + 1 - -16.465145 + -16.465144 145.637746 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMPickersgill Reeflegnum15usrmrkPickersgill Reefselect2 - attr=grpnamROUTENAME + + 1 - -15.921815 + -15.921814 145.481079 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMGubbinslegnum16usrmrkGubbinsselect2 - attr=grpnamROUTENAME + + 1 - -15.708467 - 145.382747 + -15.708466 + 145.382746 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMThree Isleslegnum17usrmrkThree Islesselect2 - attr=grpnamROUTENAME + + 1 - -15.110153 + -15.110152 145.402742 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMPalfreylegnum18usrmrkPalfreyselect2 - attr=grpnamROUTENAME + + 1 -14.673488 - 145.417741 + 145.417740 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMNymph Islandlegnum19usrmrkNymph Islandselect2 - attr=grpnamROUTENAME + + 1 -14.626822 - 145.251076 + 145.251075 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMCoquetlegnum20usrmrkCoquetselect2 - attr=grpnamROUTENAME + + 1 - -14.546824 - 145.061078 + -14.546823 + 145.061077 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMHowicklegnum21usrmrkHowickselect2 - attr=grpnamROUTENAME + + 1 - -14.483492 - 144.979412 + -14.483491 + 144.979411 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMMegaeralegnum22usrmrkMegaeraselect2 - attr=grpnamROUTENAME + + 1 - -14.483492 - 144.932746 + -14.483491 + 144.932745 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMWatsonlegnum23usrmrkWatsonselect2 - attr=grpnamROUTENAME + + 1 - -14.451826 - 144.902746 + -14.451825 + 144.902745 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMBarrowlegnum24usrmrkBarrowselect2 - attr=grpnamROUTENAME + + 1 -14.361826 - 144.686082 + 144.686081 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMRocky Pointlegnum25usrmrkRocky Pointselect2 - attr=grpnamROUTENAME + + 1 -14.195161 144.604414 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMPiponlegnum26usrmrkPiponselect2 - attr=grpnamROUTENAME + + 1 -14.138495 144.511082 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMKing Islandlegnum27usrmrkKing Islandselect2 - attr=grpnamROUTENAME + + 1 - -14.060164 - 144.331084 + -14.060163 + 144.331083 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMClack Islandlegnum28usrmrkClack Islandselect2 - attr=grpnamROUTENAME + + 1 -14.101829 144.244418 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMWharton Reeflegnum29usrmrkWharton Reefselect2 - attr=grpnamROUTENAME + + 1 -14.101831 - 143.977755 + 143.977754 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMEdenlegnum30usrmrkEdenselect2 - attr=grpnamROUTENAME + + 1 - -14.065165 - 143.917756 + -14.065164 + 143.917755 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMStainer Reeflegnum31usrmrkStainer Reefselect2 - attr=grpnamROUTENAME + + 1 -13.981832 143.834422 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMPelicanlegnum32usrmrkPelicanselect2 - attr=grpnamROUTENAME + + 1 - -13.915167 - 143.812756 + -13.915166 + 143.812755 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMMagpielegnum33usrmrkMagpieselect2 - attr=grpnamROUTENAME + + 1 -13.815167 143.734423 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMFifelegnum34usrmrkFifeselect2 - attr=grpnamROUTENAME + + 1 - -13.656835 + -13.656834 143.704422 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMHeath Reeflegnum35usrmrkHeath Reefselect2 - attr=grpnamROUTENAME + + 1 - -13.475170 - 143.671089 + -13.475169 + 143.671088 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMBow Reeflegnum36usrmrkBow Reefselect2 - attr=grpnamROUTENAME + + 1 -13.341836 - 143.671089 + 143.671088 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMOsbornelegnum37usrmrkOsborneselect2 - attr=grpnamROUTENAME + + 1 -13.096838 143.611087 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMChapmanlegnum38usrmrkChapmanselect2 - attr=grpnamROUTENAME + + 1 -12.886839 143.594420 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMWye Reeflegnum39usrmrkWye Reefselect2 - attr=grpnamROUTENAME + + 1 -12.818506 143.586087 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMEel Reeflegnum40usrmrkEel Reefselect2 - attr=grpnamROUTENAME + + 1 -12.415159 143.362754 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMPiperlegnum41usrmrkPiperselect2 - attr=grpnamROUTENAME + + 1 -12.236844 143.247755 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMMoodylegnum42usrmrkMoodyselect2 - attr=grpnamROUTENAME + + 1 -12.085178 143.239421 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMClerkelegnum43usrmrkClerkeselect2 - attr=grpnamROUTENAME + + 1 - -11.963513 - 143.317754 + -11.963512 + 143.317753 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMHanniballegnum44usrmrkHannibalselect2 - attr=grpnamROUTENAME + + 1 - -11.586850 - 142.981089 + -11.586849 + 142.981088 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMHalfwaylegnum45usrmrkHalfwayselect2 - attr=grpnamROUTENAME + + 1 -11.378517 142.986088 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMCairncrosslegnum46usrmrkCairncrossselect2 - attr=grpnamROUTENAME + + 1 -11.231851 - 142.954422 + 142.954421 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMWybornlegnum47usrmrkWybornselect2 - attr=grpnamROUTENAME + + 1 -10.806855 142.804421 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMAlbany Rocklegnum48usrmrkAlbany Rockselect2 - attr=grpnamROUTENAME + + 1 - -10.741856 + -10.741855 142.676089 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMAlpha Rocklegnum49usrmrkAlpha Rockselect2 - attr=grpnamROUTENAME + + 1 -10.601857 142.552756 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMHerald Patcheslegnum50usrmrkHerald Patchesselect2 - attr=grpnamROUTENAME + + 1 - -10.501859 - 142.377759 + -10.501858 + 142.377758 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMEast Strait Leadslegnum51usrmrkEast Strait Leadsselect2 - attr=grpnamROUTENAME + + 1 -10.480192 - 142.334426 + 142.334425 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMShadwell Pointlegnum52usrmrkShadwell Pointselect2 - attr=grpnamROUTENAME + + 1 - -10.495193 - 142.282760 + -10.495192 + 142.282759 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMNardanalegnum53usrmrkNardanaselect2 - attr=grpnamROUTENAME + + 1 -10.508525 - 142.251094 + 142.251093 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMHammondlegnum54usrmrkHammondselect2 - attr=grpnamROUTENAME + + 1 - -10.510193 - 142.202761 + -10.510192 + 142.202760 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMHarrisonlegnum55usrmrkHarrisonselect2 - attr=grpnamROUTENAME + + 1 - -10.561860 + -10.561859 142.126094 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMB1legnum56usrmrkB1select2 - attr=grpnamROUTENAME + + 1 - -10.568518 - 141.909434 + -10.568517 + 141.909433 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMRed Bankslegnum57usrmrkRed Banksselect2 - attr=grpnamROUTENAME + + 1 - -10.829183 - 141.659174 + -10.829182 + 141.659173 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMDuyfken Ptlegnum58usrmrkDuyfken Ptselect2 - attr=grpnamROUTENAME + + 1 -12.568516 141.501109 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMWeipa Leadslegnum59usrmrkWeipa Leadsselect2 - attr=grpnamROUTENAME + + 1 -12.705000 141.661667 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMWeipa FWBlegnum60usrmrkWeipa FWBselect2 - attr=grpnamROUTENAME + + 1 -12.700000 141.688333 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMGannetlegnum61usrmrkGannetselect2 - attr=grpnamROUTENAME + + 1 -10.590757 141.875120 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMB2legnum62usrmrkB2select2 - attr=grpnamROUTENAME + + 1 -10.575158 141.891066 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMMid Decaplegnum63usrmrkMid Decapselect2 - attr=grpnamROUTENAME + + 1 -14.965864 145.407427 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMTurtlelegnum64usrmrkTurtleselect2 - attr=grpnamROUTENAME + + 1 -14.632647 - 145.189251 + 145.189250 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMNewtonlegnum65usrmrkNewtonselect2 - attr=grpnamROUTENAME + + 1 - -14.517176 - 144.911975 + -14.517175 + 144.911974 diff --git a/reference/an1-an1.ref b/reference/an1-an1.ref new file mode 100644 index 0000000000000000000000000000000000000000..17df313dda5810ea4d6ea27f5263b5f2669eec95 GIT binary patch literal 2958 zcmbW&O-NKx6bJA-uQ79Say}eCrkb8J&OBYXQ2JO@Vu?_TNE!~2DU~gxPUTmtT17#w zTSS`{LQ*X%YSqG`U5ge`A_i{eBQYDDgc4U$=Zyp>Ax@nO_r3exeemPl|K;6eizzkB zMCtA+jhjLU_S<1xe{x@0=EjkLV~oEv|NG)Mor9MzoVU~Gu8i8p(wSI$zw>M=IN5Bv zz1B*b`}W^0^qN<=nZRlZ{Hz932M}(5;$S&}5eb}AgY$b4o)kH_g}@pKoL7SnTM?$b zJi`hCYbEfD8obxDF+(4LbrQIs1}9D<^iA_6-AZ7+1b$V6BPS7V7C2Z*U{nGNYOw7D z!u>Lyp`XC*61b=a@7_X~ndB92BXEZVE~&x9b%eE#9IPU6rvw(&;LKHo;sOT)1jZ!r zn;LvDgm8A1gFym!N#L>?eD6azl;oQxM4&B!nS(E6V3@!L3CyZN_p}&yIOriTE`d2U_@Wmf5#wMrfe8uBtHI8n7h!ZC2O|VFO5mIt zbTb^-&%qi3lM|8AO79k`*wS^`rNm{o&rhDUev3hM}TBrvB2AD1J< o(;TcPut@^*YS3{Imi_>v1U5_H_@n%*!Zph9`@d&sxqk=q3n|!;D*ylh literal 0 HcmV?d00001 diff --git a/reference/an1-in.ref b/reference/an1-in.ref new file mode 100644 index 000000000..a374b9984 --- /dev/null +++ b/reference/an1-in.ref @@ -0,0 +1,26 @@ +41.11111, -85.16351, +41.11048, -85.16341, +41.10986, -85.16348, +41.10908, -85.16357, +41.11138, -85.16216, +41.11058, -85.16223, +41.10990, -85.16239, +41.10923, -85.16255, +41.11138, -85.16130, +41.11068, -85.16127, +41.11000, -85.16139, +41.10920, -85.16155, +41.11142, -85.16002, +41.11075, -85.16030, +41.11005, -85.16050, +41.10964, -85.16062, +41.10824, -85.16373, +41.10821, -85.16300, +41.10817, -85.16216, +41.10846, -85.16123, +41.10768, -85.16409, +41.10756, -85.16300, +41.10768, -85.16210, +41.10778, -85.16123, +41.10684, -85.16383, +41.10681, -85.16287, diff --git a/reference/an1-line-out.ref b/reference/an1-line-out.ref new file mode 100644 index 0000000000000000000000000000000000000000..95182803e6e5889cd9f89b057d4577a3668d1232 GIT binary patch literal 1848 zcmaLXZA?#590%~*)4xOyBt%0|UbyGn@d67?Y?U@;`o2j`*{l~b50j_;EBYI?dO?|o zYE5IJJQSl@X0|q?NHtS7sWwj|+AIo5&cAWL``fO2x8FUVeRt0Jo%7;G2yOgv|5M%6 zH&{CqAGko%0@c`Ez0SurUdL4R7$32?YdaL2^E55SAyJYSkoDJ}@+BtkarKj(beYOu zXVF6kC62_==al;v)75zrXF~t)niC4K6-~G-0ocYio?V)_3mrl)*sBfk- z>=LOBt`523>SMKZotht1Wo_sFb1RuU?`u&R-FsOgIggI4b9MJUSNp$kb*Zo6GXGz{ zRe8vMuJ5#Cx2sFjtUcgkz-BOa+CG&Y^fvJEho5=h!!`r{ee`+d@~8BOmw~SP^d;qQ zwX~)jTtZ**G*Gmc_Eb(zqtiSLyo;i5xf`espeMT-@Ov}K>~H&+#Ev_3%cw->aXMVN zB$KxPl&D=tcYl`%2&9*NlX%uP(Om!iki>>6y6me&^CoL2e34iynO7=ri?sGhwSL4r z=7p-CqjTw*>U_&*Tl?2%i3%U)wwDr%-};*U$32la+e#-iN;t04rKcp8?y`1Mu|)f3 z=C5{26fC3L5+#a9Cz$&M>FWQ`L_eP*ajKlo@RnFrKtCQ3h)t(^J_z`w(Cc3dtVpEi zbPG75>5Nu^)sb}YBLOX(p4ceR;YEiw2)uHmPh1nI8SyduZ>Sc?9Hx^_3$*pphl>R| zTj~TAAnE)^W3*jxW-2H=B+=pd&P$-nCKX uQFL~!4o8@^#Tp&`q0H+dbgUeUhvaZyi~PwkB(znXbb=p8p1zvQcsX literal 0 HcmV?d00001 diff --git a/reference/an1-out.ref b/reference/an1-out.ref new file mode 100644 index 0000000000000000000000000000000000000000..bcaff7772145afe3a433d5bc9627b06f7818497b GIT binary patch literal 280 zcmY$@WdH*v1|}fQ2xfDX_lGQa`ZE{80|_xRGJ3k%C8QUWtNpVsb_*D}!TEW@63*IlCnF^_KF0tmu+R{TFEOkN p*_F+jhw2PLG-rq~1efIJr6v{S=V$A>7o}DfgSZq}4hjbb1^^U_EZqPA literal 0 HcmV?d00001 diff --git a/reference/coastexp.nob b/reference/coastexp.nob new file mode 100644 index 000000000..899175639 --- /dev/null +++ b/reference/coastexp.nob @@ -0,0 +1,370 @@ + + + Navigation Objects + true + + 34.867273 N 120.589158 W + 98208.414698 + true + true + + + + {76e5356a-d5fc-4437-8649-026416c2b185} + {d5dbd16f-eeba-4f61-b38f-582b584e5db3} + {9816402a-51a6-4fd5-8c08-b680d23d7911} + {427ed2ff-bdbb-4d77-b859-1f1eff10c961} + {0ead9569-64f0-4fb8-9545-4fa3191bbab0} + {fbe5b26d-b111-4208-ac70-f22b169d9c3e} + {68cfe23d-2ebf-4075-9726-f743659c7df5} + {50740d73-e743-4197-a6a0-29ad3114107a} + {26ae0ba0-a73e-4600-b51a-546d7099c809} + {b7266cd5-817b-4674-862e-490230a2f925} + + + 5.0 kn + + + 5.0 kn + + + 5.0 kn + + + 5.0 kn + + + 5.0 kn + + + 5.0 kn + + + 5.0 kn + + + 5.0 kn + + + 5.0 kn + + + 5.0 kn + + true + 39.06 NM + 20050516T070000 + first-waypoint + Into The Bay + + + 37.763290 N 122.282580 W + Home + 0.05 NM + 0 NM + -51,-21 + 0,24 + SFBALBAY + + + 37.751613 N 122.339028 W + 0.05 NM + 0 NM + -58,4 + 0,24 + SFBAY001 + + + 37.817420 N 122.394305 W + 0.05 NM + 0 NM + -9,-19 + 0,24 + SFBAY002 + + + 37.819339 N 122.478302 W + 0.05 NM + 0 NM + -53,-21 + 0,24 + SFGGBRDG + + + 37.773033 N 122.605838 W + 0.05 NM + 0 NM + -92,-13 + 0,24 + SFCHNL01 + + + 37.518860 N 122.529914 W + 0.05 NM + 0 NM + -98,-4 + 0,24 + HMCOLREF + + + 37.482348 N 122.507704 W + 0.05 NM + 0 NM + -77,1 + 0,24 + HMPILL01 + + + 37.476448 N 122.475800 W + 0.05 NM + 0 NM + 13,-1 + 0,24 + HMPILL02 + + + 37.495102 N 122.483927 W + 0.05 NM + 0 NM + -91,-4 + 0,24 + HMPILL03 + + + 37.229349 N 122.441589 W + 0.05 NM + 0 NM + -95,-4 + 0,24 + PESCDR01 + + + 37.183397 N 122.411904 W + 0.05 NM + 0 NM + -90,-2 + 0,24 + PIGEON01 + + + 37.090736 N 122.348775 W + 0.05 NM + 0 NM + -89,0 + 0,24 + ANONUV01 + + + 36.929502 N 122.113725 W + 0.05 NM + 0 NM + -51,4 + 0,24 + SCRUZ01 + + + 36.934235 N 122.022130 W + 0.05 NM + 0 NM + 22,-8 + 0,24 + SCRUZ02 + + + 36.960666 N 122.024734 W + 0.05 NM + 0 NM + 22,-9 + 0,24 + SCRUZENT + + + 37.475062 N 122.488531 W + 0.05 NM + 0 NM + -44,5 + 0,24 + HMPILLPT + + + 36.581344 N 121.995411 W + 0.05 NM + 0 NM + -95,-7 + 0,24 + CYPRSSPT + + + 36.301110 N 121.919097 W + 0.05 NM + 0 NM + -67,-3 + 0,24 + PTSUR + + + 36.238177 N 121.855209 W + 0.05 NM + 0 NM + -72,3 + 0,24 + COOPERPT + + + 36.225175 N 121.801314 W + 0.05 NM + 0 NM + -91,-8 + 0,24 + PFEIFENT + + + 36.230449 N 121.797444 W + Anchor + 0.05 NM + 0 NM + -85,-14 + 0,24 + PFEIFANC + + + 35.879801 N 121.498947 W + 0.05 NM + 0 NM + 10,-15 + 0,24 + SANMRT01 + + + 35.652801 N 121.308485 W + 0.05 NM + 0 NM + -75,2 + 0,24 + PDRSBLNC + + + 35.623297 N 121.185920 W + 0.05 NM + 0 NM + -102,-6 + 0,24 + SNSMNENT + + + 35.640478 N 121.183772 W + Anchor + 0.05 NM + 0 NM + -105,-9 + 0,24 + SNSMNANC + + + 35.572353 N 121.152797 W + 0.05 NM + 0 NM + -80,-1 + 0,24 + CAMBRIA + + + 35.449214 N 121.020825 W + 0.05 NM + 0 NM + 14,-14 + 0,24 + PTESTERO + + + 35.216602 N 120.928391 W + 0.05 NM + 0 NM + -96,-3 + 0,24 + PTBUCHON + + + 34.883361 N 120.684631 W + 0.05 NM + 0 NM + -57,3 + 0,24 + PTSAL01 + + + 34.884641 N 120.652026 W + 0.05 NM + 0 NM + -96,-8 + 0,24 + PTSALENT + A description of the Point Sal Entrance mark + + + 34.896555 N 120.649124 W + Anchor + 0.05 NM + 0 NM + -96,-10 + 0,24 + PTSALANC + + + 34.758180 N 120.642516 W + 0.05 NM + 0 NM + 22,-8 + 0,24 + PURSMAPT + + + 34.572579 N 120.663636 W + 0.05 NM + 0 NM + -97,-7 + 0,24 + PTARGLLO + + + 34.113844 N 120.492630 W + 0.05 NM + 0 NM + 20,-11 + 0,24 + SANMGL01 + + + 34.029483 N 120.471409 W + 0.05 NM + 0 NM + -88,0 + 0,24 + SANMGL02 + + + 34.019184 N 120.444197 W + 0.05 NM + 0 NM + -32,5 + 0,24 + SANMGL03 + + + 34.023478 N 120.438209 W + 0.05 NM + 0 NM + 19,-4 + 0,24 + ADCOVENT + + + 34.028615 N 120.439696 W + Anchor + 0.05 NM + 0 NM + -102,-5 + 0,24 + ADCOVANC + + diff --git a/reference/coastexp.ref b/reference/coastexp.ref new file mode 100644 index 000000000..98df894e3 --- /dev/null +++ b/reference/coastexp.ref @@ -0,0 +1,221 @@ + + + + + + + PESCDR01 + PESCDR01 + PESCDR01 + + + + PIGEON01 + PIGEON01 + PIGEON01 + + + + ANONUV01 + ANONUV01 + ANONUV01 + + + + SCRUZ01 + SCRUZ01 + SCRUZ01 + + + + SCRUZ02 + SCRUZ02 + SCRUZ02 + + + + SCRUZENT + SCRUZENT + SCRUZENT + + + + CYPRSSPT + CYPRSSPT + CYPRSSPT + + + + PTSUR + PTSUR + PTSUR + + + + COOPERPT + COOPERPT + COOPERPT + + + + PFEIFENT + PFEIFENT + PFEIFENT + + + + PFEIFANC + PFEIFANC + PFEIFANC + + + + SANMRT01 + SANMRT01 + SANMRT01 + + + + PDRSBLNC + PDRSBLNC + PDRSBLNC + + + + SNSMNENT + SNSMNENT + SNSMNENT + + + + SNSMNANC + SNSMNANC + SNSMNANC + + + + CAMBRIA + CAMBRIA + CAMBRIA + + + + PTESTERO + PTESTERO + PTESTERO + + + + PTBUCHON + PTBUCHON + PTBUCHON + + + + PTSAL01 + PTSAL01 + PTSAL01 + + + + PTSALENT + A description of the Point Sal Entrance mark + A description of the Point Sal Entrance mark + + + + PTSALANC + PTSALANC + PTSALANC + + + + PURSMAPT + PURSMAPT + PURSMAPT + + + + PTARGLLO + PTARGLLO + PTARGLLO + + + + SANMGL01 + SANMGL01 + SANMGL01 + + + + SANMGL02 + SANMGL02 + SANMGL02 + + + + SANMGL03 + SANMGL03 + SANMGL03 + + + + ADCOVENT + ADCOVENT + ADCOVENT + + + + ADCOVANC + ADCOVANC + ADCOVANC + + + Into The Bay + + + SFBALBAY + + + + SFBAY001 + + + + SFBAY002 + + + + SFGGBRDG + + + + SFCHNL01 + + + + HMCOLREF + + + + HMPILL01 + + + + HMPILLPT + + + + HMPILL02 + + + + HMPILL03 + + + diff --git a/reference/coastexp.ref2 b/reference/coastexp.ref2 new file mode 100644 index 000000000..d5a7be89e --- /dev/null +++ b/reference/coastexp.ref2 @@ -0,0 +1,171 @@ + + + Navigation Objects + + + {10111213-1415-1617-1819-1a1b1c1d1e1f} + {20212223-2425-2627-2829-2a2b2c2d2e2f} + {30313233-3435-3637-3839-3a3b3c3d3e3f} + {40414243-4445-4647-4849-4a4b4c4d4e4f} + {50515253-5455-5657-5859-5a5b5c5d5e5f} + {60616263-6465-6667-6869-6a6b6c6d6e6f} + {70717273-7475-7677-7879-7a7b7c7d7e7f} + {80818283-8485-8687-8889-8a8b8c8d8e8f} + {90919293-9495-9697-9899-9a9b9c9d9e9f} + {a0a1a2a3-a4a5-a6a7-a8a9-aaabacadaeaf} + + Into The Bay + + + 37.763290 N 122.282580 W + SFBALBAY + + + 37.751613 N 122.339028 W + SFBAY001 + + + 37.817420 N 122.394305 W + SFBAY002 + + + 37.819339 N 122.478302 W + SFGGBRDG + + + 37.773033 N 122.605838 W + SFCHNL01 + + + 37.518860 N 122.529914 W + HMCOLREF + + + 37.482348 N 122.507704 W + HMPILL01 + + + 37.475062 N 122.488531 W + HMPILLPT + + + 37.476448 N 122.475800 W + HMPILL02 + + + 37.495102 N 122.483927 W + HMPILL03 + + + 37.229349 N 122.441589 W + PESCDR01 + + + 37.183397 N 122.411904 W + PIGEON01 + + + 37.090736 N 122.348775 W + ANONUV01 + + + 36.929502 N 122.113725 W + SCRUZ01 + + + 36.934235 N 122.022130 W + SCRUZ02 + + + 36.960666 N 122.024734 W + SCRUZENT + + + 36.581344 N 121.995411 W + CYPRSSPT + + + 36.301110 N 121.919097 W + PTSUR + + + 36.238177 N 121.855209 W + COOPERPT + + + 36.225175 N 121.801314 W + PFEIFENT + + + 36.230449 N 121.797444 W + PFEIFANC + + + 35.879801 N 121.498947 W + SANMRT01 + + + 35.652801 N 121.308485 W + PDRSBLNC + + + 35.623297 N 121.185920 W + SNSMNENT + + + 35.640478 N 121.183772 W + SNSMNANC + + + 35.572353 N 121.152797 W + CAMBRIA + + + 35.449214 N 121.020825 W + PTESTERO + + + 35.216602 N 120.928391 W + PTBUCHON + + + 34.883361 N 120.684631 W + PTSAL01 + + + 34.884641 N 120.652026 W + PTSALENT + + + 34.896555 N 120.649124 W + PTSALANC + + + 34.758180 N 120.642516 W + PURSMAPT + + + 34.572579 N 120.663636 W + PTARGLLO + + + 34.113844 N 120.492630 W + SANMGL01 + + + 34.029483 N 120.471409 W + SANMGL02 + + + 34.019184 N 120.444197 W + SANMGL03 + + + 34.023478 N 120.438209 W + ADCOVENT + + + 34.028615 N 120.439696 W + ADCOVANC + + diff --git a/reference/coastexp.ref3 b/reference/coastexp.ref3 new file mode 100644 index 000000000..9c32e3678 --- /dev/null +++ b/reference/coastexp.ref3 @@ -0,0 +1,238 @@ + + + + + + + SFBALBAY + SFBALBAY + SFBALBAY + + + + SFBAY001 + SFBAY001 + SFBAY001 + + + + SFBAY002 + SFBAY002 + SFBAY002 + + + + SFGGBRDG + SFGGBRDG + SFGGBRDG + + + + SFCHNL01 + SFCHNL01 + SFCHNL01 + + + + HMCOLREF + HMCOLREF + HMCOLREF + + + + HMPILL01 + HMPILL01 + HMPILL01 + + + + HMPILL02 + HMPILL02 + HMPILL02 + + + + HMPILL03 + HMPILL03 + HMPILL03 + + + + PESCDR01 + PESCDR01 + PESCDR01 + + + + PIGEON01 + PIGEON01 + PIGEON01 + + + + ANONUV01 + ANONUV01 + ANONUV01 + + + + SCRUZ01 + SCRUZ01 + SCRUZ01 + + + + SCRUZ02 + SCRUZ02 + SCRUZ02 + + + + SCRUZENT + SCRUZENT + SCRUZENT + + + + HMPILLPT + HMPILLPT + HMPILLPT + + + + CYPRSSPT + CYPRSSPT + CYPRSSPT + + + + PTSUR + PTSUR + PTSUR + + + + COOPERPT + COOPERPT + COOPERPT + + + + PFEIFENT + PFEIFENT + PFEIFENT + + + + PFEIFANC + PFEIFANC + PFEIFANC + + + + SANMRT01 + SANMRT01 + SANMRT01 + + + + PDRSBLNC + PDRSBLNC + PDRSBLNC + + + + SNSMNENT + SNSMNENT + SNSMNENT + + + + SNSMNANC + SNSMNANC + SNSMNANC + + + + CAMBRIA + CAMBRIA + CAMBRIA + + + + PTESTERO + PTESTERO + PTESTERO + + + + PTBUCHON + PTBUCHON + PTBUCHON + + + + PTSAL01 + PTSAL01 + PTSAL01 + + + + PTSALENT + A description of the Point Sal Entrance mark + A description of the Point Sal Entrance mark + + + + PTSALANC + PTSALANC + PTSALANC + + + + PURSMAPT + PURSMAPT + PURSMAPT + + + + PTARGLLO + PTARGLLO + PTARGLLO + + + + SANMGL01 + SANMGL01 + SANMGL01 + + + + SANMGL02 + SANMGL02 + SANMGL02 + + + + SANMGL03 + SANMGL03 + SANMGL03 + + + + ADCOVENT + ADCOVENT + ADCOVENT + + + + ADCOVANC + ADCOVANC + ADCOVANC + + diff --git a/reference/coastexp.ref4 b/reference/coastexp.ref4 new file mode 100644 index 000000000..20faa6aaa --- /dev/null +++ b/reference/coastexp.ref4 @@ -0,0 +1,156 @@ + + + Navigation Objects + + 37.763290 N 122.282580 W + SFBALBAY + + + 37.751613 N 122.339028 W + SFBAY001 + + + 37.817420 N 122.394305 W + SFBAY002 + + + 37.819339 N 122.478302 W + SFGGBRDG + + + 37.773033 N 122.605838 W + SFCHNL01 + + + 37.518860 N 122.529914 W + HMCOLREF + + + 37.482348 N 122.507704 W + HMPILL01 + + + 37.476448 N 122.475800 W + HMPILL02 + + + 37.495102 N 122.483927 W + HMPILL03 + + + 37.229349 N 122.441589 W + PESCDR01 + + + 37.183397 N 122.411904 W + PIGEON01 + + + 37.090736 N 122.348775 W + ANONUV01 + + + 36.929502 N 122.113725 W + SCRUZ01 + + + 36.934235 N 122.022130 W + SCRUZ02 + + + 36.960666 N 122.024734 W + SCRUZENT + + + 37.475062 N 122.488531 W + HMPILLPT + + + 36.581344 N 121.995411 W + CYPRSSPT + + + 36.301110 N 121.919097 W + PTSUR + + + 36.238177 N 121.855209 W + COOPERPT + + + 36.225175 N 121.801314 W + PFEIFENT + + + 36.230449 N 121.797444 W + PFEIFANC + + + 35.879801 N 121.498947 W + SANMRT01 + + + 35.652801 N 121.308485 W + PDRSBLNC + + + 35.623297 N 121.185920 W + SNSMNENT + + + 35.640478 N 121.183772 W + SNSMNANC + + + 35.572353 N 121.152797 W + CAMBRIA + + + 35.449214 N 121.020825 W + PTESTERO + + + 35.216602 N 120.928391 W + PTBUCHON + + + 34.883361 N 120.684631 W + PTSAL01 + + + 34.884641 N 120.652026 W + PTSALENT + + + 34.896555 N 120.649124 W + PTSALANC + + + 34.758180 N 120.642516 W + PURSMAPT + + + 34.572579 N 120.663636 W + PTARGLLO + + + 34.113844 N 120.492630 W + SANMGL01 + + + 34.029483 N 120.471409 W + SANMGL02 + + + 34.019184 N 120.444197 W + SANMGL03 + + + 34.023478 N 120.438209 W + ADCOVENT + + + 34.028615 N 120.439696 W + ADCOVANC + + diff --git a/reference/foo.an1 b/reference/foo.an1 new file mode 100644 index 0000000000000000000000000000000000000000..ae27a48004bbb61bd81e06eb5fef4137fedce326 GIT binary patch literal 135252 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 literal 0 HcmV?d00001 diff --git a/reference/google.arc b/reference/google.arc new file mode 100644 index 000000000..c216f18c3 --- /dev/null +++ b/reference/google.arc @@ -0,0 +1,111 @@ +41.87895 -87.63665 +41.87924 -87.63666 +41.87937 -87.63666 +41.87952 -87.63667 +41.88063 -87.63672 +41.88126 -87.63673 +41.88194 -87.63676 +41.88194 -87.63676 +41.88206 -87.63676 +41.88257 -87.63678 +41.88301 -87.63679 +41.88318 -87.63678 +41.88380 -87.63681 +41.88447 -87.63683 +41.88506 -87.63686 +41.88519 -87.63686 +41.88542 -87.63686 +41.88574 -87.63682 +41.88574 -87.63682 +41.88583 -87.63678 +41.88595 -87.63666 +41.88677 -87.63538 +41.88677 -87.63528 +41.88677 -87.63477 +41.88677 -87.63394 +41.88677 -87.63249 +41.88677 -87.63249 +41.88696 -87.63248 +41.88710 -87.63248 +41.88780 -87.63248 +41.88780 -87.63248 +41.88919 -87.63254 +41.89000 -87.63254 +41.89078 -87.63257 +41.89160 -87.63260 +41.89198 -87.63261 +41.89240 -87.63263 +41.89322 -87.63264 +41.89401 -87.63266 +41.89482 -87.63267 +41.89562 -87.63269 +41.89664 -87.63271 +41.89796 -87.63273 +41.89926 -87.63278 +41.90053 -87.63283 +41.90183 -87.63288 +41.90312 -87.63290 +41.90388 -87.63292 +41.90576 -87.63300 +41.90772 -87.63305 +41.90917 -87.63309 +41.91117 -87.63313 +41.91117 -87.63313 +41.91265 -87.63317 +41.91289 -87.63316 +41.91289 -87.63316 +41.91299 -87.63310 +41.91307 -87.63301 +41.91314 -87.63284 +41.91314 -87.63284 +41.91380 -87.63324 +41.91485 -87.63388 +41.91560 -87.63433 +41.91658 -87.63494 +41.91842 -87.63603 +41.91842 -87.63603 +41.91889 -87.63636 +41.92015 -87.63718 +41.92195 -87.63822 +41.92374 -87.63928 +41.92497 -87.64005 +41.92556 -87.64040 +41.92678 -87.64115 +41.92697 -87.64127 +41.92730 -87.64147 +41.92778 -87.64172 +41.92852 -87.64217 +41.92865 -87.64224 +41.92951 -87.64276 +41.92963 -87.64288 +41.92982 -87.64311 +41.92995 -87.64335 +41.93067 -87.64382 +41.93131 -87.64418 +41.93180 -87.64449 +41.93208 -87.64466 +41.93242 -87.64479 +41.93277 -87.64483 +41.93277 -87.64483 +41.93368 -87.64551 +41.93452 -87.64622 +41.93478 -87.64645 +41.93549 -87.64700 +41.93558 -87.64707 +41.93639 -87.64774 +41.93780 -87.64888 +41.93811 -87.64913 +41.93811 -87.64913 +41.93903 -87.64986 +41.93992 -87.65062 +41.94175 -87.65203 +41.94241 -87.65255 +41.94352 -87.65349 +41.94429 -87.65410 +41.94429 -87.65410 +41.94443 -87.65420 +41.94558 -87.65510 +41.94654 -87.65592 +41.94718 -87.65639 +41.94718 -87.65639 +41.94719 -87.65553 diff --git a/reference/google.js b/reference/google.js new file mode 100644 index 000000000..de2e30b71 --- /dev/null +++ b/reference/google.js @@ -0,0 +1,2 @@ +Google Maps - 233 S. Wacker, Chicago, IL to 1060 W. Addison, Chicago, IL \ No newline at end of file diff --git a/reference/google.xml b/reference/google.xml new file mode 100644 index 000000000..33ff7f308 --- /dev/null +++ b/reference/google.xml @@ -0,0 +1 @@ +233 S. Wacker, Chicago, IL to 1060 W. Addison, Chicago, IL233 S. Wacker, Chicago, IL to 1060 W. Addison, Chicago, IL
233 S Upper Wacker DrChicago, IL 60606
1060 W Addison StChicago, IL 60613
mnr~F`p{uOy@@Y?]@}EH}B@gCD??W?eBBwA@a@A{BDeCBuBDY?m@?_AG??QGWWcD_G?S?eB?eD?aH??e@A[?kC???uGJaD?{CDcDDkA@sABcD@}CBaD@_DBkEBgGBcGH}FHcGHaGBwCBwJNgKHaHFoKF??gHFo@A??SKOQMa@??cCnAqE~BuCxAcExBoJxE??}A`A{FbDgJnEeJrEuFxCuBdAsFtCe@VaAf@_Bp@sCxAYLkDfBWVe@l@Yn@oC|A_CfAaB|@w@`@cAXeAF??uDfCgDlCs@l@mClBQLaDdCyGbF}@p@??wDpCqDvCmJxGcCfB}EzDyCxB??[ReFrD_EbD_C|A??AkDB?????BB??????@??BB?@@???BB??BB?????@?????@?????@??BB?BB?@BB????@??@?@????@???@?@@@??@@A?@?????????@?@@?????BBBHead north from S Upper Wacker DrContinue on N Upper Wacker DrBear right at W Upper Wacker DrTurn left at N La Salle StContinue on N La Salle BlvdContinue on N La Salle DrBear right at W Eugenie StTurn left at N Clark StTurn right at W Addison St
\ No newline at end of file diff --git a/reference/googmap.sh b/reference/googmap.sh new file mode 100644 index 000000000..83a73d32c --- /dev/null +++ b/reference/googmap.sh @@ -0,0 +1,5 @@ + +FROM="233 S. Wacker, Chicago, IL" +TO="1060 W. Addison, Chicago, IL" +wget -O - "http://maps.google.com/maps?q=$FROM to $TO&output=xml" 2>/dev/null + diff --git a/reference/googmapjs.sh b/reference/googmapjs.sh new file mode 100644 index 000000000..6ce53183b --- /dev/null +++ b/reference/googmapjs.sh @@ -0,0 +1,5 @@ + +FROM="233 S. Wacker, Chicago, IL" +TO="1060 W. Addison, Chicago, IL" +wget -O - "http://maps.google.com/maps?q=$FROM to $TO&output=js" 2>/dev/null + diff --git a/reference/hsandv.exp b/reference/hsandv.exp index 78c979a7d..0f3b43070 100644 --- a/reference/hsandv.exp +++ b/reference/hsandv.exp @@ -6,72 +6,72 @@ 0 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMGCEBBlegnum0usrmrkMountain Bike Heaven by susy1313select2 - attr=grpnamROUTENAME + + 1 35.972033 -87.134700 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMGC1A37legnum1usrmrkThe Troll by a182pilot & Familyselect2 - attr=grpnamROUTENAME + + 1 36.090683 -86.679550 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMGC1C2Blegnum2usrmrkDive Bomber by JoGPS & familyselect2 - attr=grpnamROUTENAME + + 1 35.996267 -86.620117 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMGC25A9legnum3usrmrkFOSTER by JoGPS & Familyselect2 - attr=grpnamROUTENAME + + 1 36.038483 -86.648617 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMGC2723legnum4usrmrkLogan Lighthouse by JoGps & Familyselect2 - attr=grpnamROUTENAME + + 1 36.112183 -86.741767 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMGC2B71legnum5usrmrkGanier Cache by Susy1313select2 - attr=grpnamROUTENAME + + 1 36.064083 -86.790517 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMGC309Flegnum6usrmrkShy's Hill by FireFighterEng33select2 - attr=grpnamROUTENAME + + 1 36.087767 -86.809733 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMGC317Alegnum7usrmrkGittyUp by JoGPS / Warner Parksselect2 - attr=grpnamROUTENAME + + 1 36.057500 -86.892000 waypnt - attr=grpnamROUTENAMEtrnrad50OBJNAMGC317Dlegnum8usrmrkInlighting by JoGPS / Warner Parksselect2 - attr=grpnamROUTENAME + + 1 36.082800 -86.867283 diff --git a/reference/igc1.gpx b/reference/igc1.gpx index 35191c176..63e3ef55d 100644 --- a/reference/igc1.gpx +++ b/reference/igc1.gpx @@ -1,30 +1,45 @@ - - - + + + PALLMG PALLMG PALLMG dot - + PILOT CHRIS JONES CHRIS JONES dot - + PLUMTH PLUMTHORPE LOC PLUMTHORPE LOC dot + + AB1 + + 0.000000 + BORAH + + + 0.000000 + BALDWI + + + 0.000000 + MANAIR + + @@ -531,19 +546,4 @@ xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/ - - AB1 - - 0.000000 - BORAH - - - 0.000000 - BALDWI - - - 0.000000 - MANAIR - - diff --git a/reference/igc1_3d.out b/reference/igc1_3d.out index 21ff7744a..2ecdeb4e2 100644 --- a/reference/igc1_3d.out +++ b/reference/igc1_3d.out @@ -48,7 +48,7 @@ B0419123040526S15036253EA0090600000 B0419433040646S15036334EA0090300000 B0420133040794S15036367EA0089500000 B0420443040707S15036367EA0090300000 -B0421143040678S15036423EA0092200000 +B0421143040679S15036423EA0092200000 B0421443040658S15036414EA0091400000 B0422153040772S15036358EA0091900000 B0422453040722S15036423EA0096100000 diff --git a/reference/igc1_gpx.out b/reference/igc1_gpx.out index 9dc64d888..25c86bb95 100644 --- a/reference/igc1_gpx.out +++ b/reference/igc1_gpx.out @@ -6,6 +6,30 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.topografix.com/GPX/1/0" xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd"> + + 0001 + IGCDATE000000: + + TAKEOFF + BORAH + + + START + BORAH + + + TURN01 + BALDWI + + + FINISH + MANAIR + + + LANDING + MANAIR + + GNSSALTTRK IGCHDRS~HFPLTPILOT:CHRIS JONES~ @@ -133,7 +157,7 @@ xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/ - + @@ -351,28 +375,4 @@ xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/ - - 0001 - IGCDATE000000: - - TAKEOFF - BORAH - - - START - BORAH - - - TURN01 - BALDWI - - - FINISH - MANAIR - - - LANDING - MANAIR - - diff --git a/reference/igc1_igc.out b/reference/igc1_igc.out index beb86d8e2..9d3c0071e 100644 --- a/reference/igc1_igc.out +++ b/reference/igc1_igc.out @@ -48,7 +48,7 @@ B0419123040526S15036253EA0000000000 B0419433040646S15036334EA0000000000 B0420133040794S15036367EA0000000000 B0420443040707S15036367EA0000000000 -B0421143040678S15036423EA0000000000 +B0421143040679S15036423EA0000000000 B0421443040658S15036414EA0000000000 B0422153040772S15036358EA0000000000 B0422453040722S15036423EA0000000000 diff --git a/reference/igc2_gpx.out b/reference/igc2_gpx.out index 6b2e34087..d841eac8e 100644 --- a/reference/igc2_gpx.out +++ b/reference/igc2_gpx.out @@ -6,44 +6,78 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.topografix.com/GPX/1/0" xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd"> + + 0001 + IGCDATE160701: 500KTri + + + TAKEOFF + LashamClubhouse + + + + START + LashamStart S Start + + + + TURN01 + Sarnesfield TP1 + + + + TURN02 + NormanCross TP2 + + + + FINISH + LashamStart S Finish + + + + LANDING + LashamClubhouse + + PRESALTTRK IGCHDRS~HFFXA035~HFPLTPILOT:Bill Bloggs~HFGTYGLIDERTYPE:Schleicher ASH-25~HFGIDGLIDERID:ABCD-1234~HFDTM100GPSDATUM:WGS-1984~HFRFWFIRMWAREVERSION:6.4~HFRHWHARDWAREVERSION:3.0~HFFTYFRTYPE:Manufacturer Model~HFGPSMarconiCanada:Superstar 12ch max10000m~HFPRSPRESSALTSENSOR:Sensyn XYZ1111 max11000m~HFCIDCOMPETITIONID:XYZ-78910~HFCCLCOMPETITIONCLASS:15mMotor Glider~HFSCMSECONDCREW:JohnSmith~ -280.000000 + 280.000000 -288.000000 + 288.000000 -290.000000 + 290.000000 -290.000000 + 290.000000 -291.000000 + 291.000000 -291.000000 + 291.000000 -293.000000 + 293.000000 -494.000000 + 494.000000 -496.000000 + 496.000000 @@ -53,75 +87,41 @@ xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/ IGCHDRS~HFFXA035~HFPLTPILOT:Bill Bloggs~HFGTYGLIDERTYPE:Schleicher ASH-25~HFGIDGLIDERID:ABCD-1234~HFDTM100GPSDATUM:WGS-1984~HFRFWFIRMWAREVERSION:6.4~HFRHWHARDWAREVERSION:3.0~HFFTYFRTYPE:Manufacturer Model~HFGPSMarconiCanada:Superstar 12ch max10000m~HFPRSPRESSALTSENSOR:Sensyn XYZ1111 max11000m~HFCIDCOMPETITIONID:XYZ-78910~HFCCLCOMPETITIONCLASS:15mMotor Glider~HFSCMSECONDCREW:JohnSmith~ -421.000000 + 421.000000 -429.000000 + 429.000000 -432.000000 + 432.000000 -430.000000 + 430.000000 -432.000000 + 432.000000 -435.000000 + 435.000000 -435.000000 + 435.000000 -436.000000 + 436.000000 -439.000000 + 439.000000 - - 0001 - IGCDATE160701: 500KTri - - - TAKEOFF - LashamClubhouse - - - - START - LashamStart S Start - - - - TURN01 - Sarnesfield TP1 - - - - TURN02 - NormanCross TP2 - - - - FINISH - LashamStart S Finish - - - - LANDING - LashamClubhouse - - diff --git a/reference/lowrance.usr b/reference/lowrance.usr new file mode 100644 index 0000000000000000000000000000000000000000..1982f8a1a27e915833378db2710bd82c8eac9f02 GIT binary patch literal 353 zcmZQ#U|`?`;{V}}3^uhn|A9;fRv>nFc6D+BaTvDbS_rCx7>o>4r#mv#I^}{Du>nQg zoedq0%|UVqRZI-OQXCoVV^CB%8=;xS%rK+ck>RO7vMM7}M@v+*SQum%J2JGXqo^`B zGDcO!$`IJ;$dD$4qRPqK5LFc$1Isi=1|cqFRmKLEZm6o*8BVo2GGsr41O&v7#)jsO XsH!*^q9!{sD1Jm!<$|gT%wqrmf`>Y7 literal 0 HcmV?d00001 diff --git a/reference/ov2-arc-out.ref b/reference/ov2-arc-out.ref new file mode 100644 index 0000000000000000000000000000000000000000..11d8ddd12fdd656d02706ddf1b33d7fff88b0762 GIT binary patch literal 2535 zcmZwITSydf7zOaz$cF+g$f6(+4T5em>)za6)-p?|KvYP|0wXcI83d72DMmpgf|z)6^?#$u*mnQC0L zShgBV5PPUWSi&?+7A6nLq}A=S>@+M|ERWZ#_ZqL)X|~j6fZ? zmhLwxE!p7EH+R1YIt^;A&I-8|#5U`y*{awXT8NL%XH49TxdokLVzJ^cZVMqMz6rad z#>6*Z<7!NN9hUKx=Q8m%SiTy!OcU&u8gn$l-m5W318gfwki22$xB|1(f~m5!K`G5C z%fg`ia872pORy7@G={qX8&zYtbFk_u&M{mqY)p;eYG5a)Imd9-ut#bPcNBJhhI0&8 z0SkY3Ey8f+u$O9lNF}hAS2=DfmNxo z!ai8J8mpd%tyJS9$tbey{$K7|VtjNtu%~LQCKq;3jXCOJ+trw(9X9im*JF+e*hMun zwFjjvDNP!5%90oLjN0?TezW8y5> zRW-KiGd__@%$YjJrk}xjZ0CstO*TCVYgFS}F7LAJz9r5v$7@)fYi68zrI*2-c;>a2BjW qjp3fd7WLi1_4$l}Utq3Z=lGD`z@Dfv#}KStjX7+X6ym&}!p1)@!`kWq literal 0 HcmV?d00001 diff --git a/reference/ov2-geo-out.ref b/reference/ov2-geo-out.ref new file mode 100644 index 0000000000000000000000000000000000000000..95d3bb5f2cb79d34df902ee35ee37db68f06bbb0 GIT binary patch literal 416 zcmZ|KKTE?v7zXgSQE@1Uu1+`A!N0MPI9HoisaTqb^Ht8|XnGfNNg>?gsH6A=9Q+u5 z09^#Z!M&?);wI-EjkSy83qPLcc`J7nfQ477daEwXRi(NeJ78@AOpjxpvkX&)8gxKV zo8S>)s9zwFi^8tkb+9(IetwYZeZ_?!A}C0C92NjvltIPYz105b>hB`EivWVw` zls*wN159duqf-}MXkkWm_dY(?v-JXh`qPG1pVv}7ExX`H#hO5EI(f>YDe+7LNt-OJ vm;b*|slMiQBF(bmH2E94jm~h&bV(Pd0|AzqTL`J%mRvYwu?eCq{MY{g06c{z literal 0 HcmV?d00001 diff --git a/reference/ov2-in.ref b/reference/ov2-in.ref new file mode 100644 index 000000000..4c0e75dee --- /dev/null +++ b/reference/ov2-in.ref @@ -0,0 +1,9 @@ +Mountain Bike Heaven by susy1313 3558.322N 08708.081W 0000000m Mountain Bike Heaven by susy13 a +The Troll by a182pilot & Family 3605.441N 08640.772W 0000000m The Troll by a182pilot & Famil a +Dive Bomber by JoGPS & family 3559.776N 08637.207W 0000000m Dive Bomber by JoGPS & family a +FOSTER by JoGPS & Family 3602.309N 08638.917W 0000000m FOSTER by JoGPS & Family a +Logan Lighthouse by JoGps & Family 3606.731N 08644.506W 0000000m Logan Lighthouse by JoGps & Fa a +Ganier Cache by Susy1313 3603.845N 08647.431W 0000000m Ganier Cache by Susy1313 a +Shy's Hill by FireFighterEng33 3605.266N 08648.583W 0000000m Shy's Hill by FireFighterEng33 a +GittyUp by JoGPS / Warner Parks 3603.450N 08653.519W 0000000m GittyUp by JoGPS / Warner Park a +Inlighting by JoGPS / Warner Parks 3604.968N 08652.036W 0000000m Inlighting by JoGPS / Warner P a diff --git a/reference/pathaway-geo.loc b/reference/pathaway-geo.loc new file mode 100644 index 000000000..8e7a0194f --- /dev/null +++ b/reference/pathaway-geo.loc @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/reference/route/route.gpx b/reference/route/route.gpx index b8d58a158..8030ff529 100644 --- a/reference/route/route.gpx +++ b/reference/route/route.gpx @@ -57,7 +57,7 @@ xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/ ATCHAFALAYA ROUTE1 -1 +2 0.000000 diff --git a/reference/route/tef_xml.mps b/reference/route/tef_xml.mps new file mode 100644 index 0000000000000000000000000000000000000000..3021af6a3ee51ffecf420135d5561d4d6e92187b GIT binary patch literal 12934 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 literal 0 HcmV?d00001 diff --git a/reference/route/tef_xml.sample.xml b/reference/route/tef_xml.sample.xml new file mode 100644 index 000000000..ddb466e4a --- /dev/null +++ b/reference/route/tef_xml.sample.xml @@ -0,0 +1,2 @@ + +
diff --git a/reference/track/TrkDB-GPil.pdb b/reference/track/TrkDB-GPil.pdb new file mode 100644 index 0000000000000000000000000000000000000000..00c0912334a2eedb12c4c1d1bd32a5d883c4d4e0 GIT binary patch literal 9544 zcmeI%d2m(L9S886gyoSvghU`9F@@|a5fIcQFZYB5Cxui3jKyja5+Fk$5GX3xs%fd3K#@c;9O?OAL?RDC1dJSZE}Kk0~mtn0l{O{2<~zzMX6s zpGQRc7!iXXH*9I9VVm+#^eke)H0!sp_S$1+bIe(fUe@P1!wkqfremAafaDproChhJ zO~u|r}hRpyEKE+TQ1 zgXYQBt&|MJBv1~Sr>jqkBvSrrp4k~lNk>c)<*<2ny%HHrsW#gV^b)b!e8jvk-MTtU z4Pnet^HQEKW6~g2-#<0KIG9X%6f&GKHRhE+JWqK9@-XF?dENU%kw+-C=2tf^b&`7X z>+rWbNuznw*BVvUW0i84w>+Cc) zVpT}C)#ir~!@ES?U1@dr>z+ z1ud|qRD;qrC(nk|Q}Xp3OU{OzqD58M=Y%52R>~%kks>?fS~xv3x!W}E7Qrr>d71LD2zF7k z2c<^&D#fec59vjz(=Cku0&+j)jE;$43E@f9ct_V0KOK?_Y4Vj)C6EkCpu|joa8#T6 zDc_SkVdFW5HI!uC(|9~GPlq@ZA-$34_JfZ7}`!{3@WunMM z2v>Jgk#0|1HH34uX_g53mH8^=WhpfgvVgKy`L;Kr&2e#%X_W0+VsApmQL6R2h;4%K zBx-UfzbC>`D)uiBe@dIk9!NLJMSX(AZZ>T8o0O{(^BRP6tm&4-EP|YaI6OqK^V^S8 zy522Zr;hG-3&+{vEj2GdDUP$lPhxNf?SG?$D!*%&*k;^8dmW{(@@wRI5&JU;=c;3X z#NaHje@2NG$%1f(JL062f>`Z|7r_&ny_GRZB6zxRNs98@%{@GJ1f+#AsUk^`2Fh^h z1?IE;1m#hY!5G#4l+hx*Uo$C_ygH$E-jvtUKrwnFZOvn9I8FF*%SI zAkALNKbg-7F#{kIDZRBsd|0Ucrqpv}RQIbS1Kon(&@*l&UHu^jyn=(}D z!3kpLlT7m{eNUs0LJm;I>-I$NgH%zT6!|lR=T7re`kqE(hTC^j3PfIoETqhqQi~zK zqRbU}2{Ml|U*t)M)r*xPoOMBr*`WM`K435KEShnVvQ64dIZyde1UpH_8OnJPJLDt< zYtWkW(P(7QCS!V;j&euJSDu6^%7K&he(s>R#7l~jO zb;T^zEsXjxgwGq!WfFrK<&qU5rpQVWj7EACOT8}j;8{IAg0fm-`a?V@oAiu|>WA-( z?UYIp%+)lWJI?n+`armkIk#(x#2%i;Q_p!w=9HIVq(+lbACiHIU!2o^$${Ka#SF(kAi=giqAYiy|LGxKf;-i)@4Zobt8u zzt9EuJ@Su`S(I;7KzE+_ky!6(<&c)HDq!Op%1lTFB~%4ITt*qC>uHHmK`Fnca16PR zwWO(_yc~)Tq>Pdy;s+_Fb&p?Z!ikZV~|{=HH&|4VLHu2F&gHsgDN)N{LXt?E+ec~?ER zE7!S1vNT0SMaKB7@Z2%kKZvBuJ$J&&(tPR8((rphtvgGDOa)FWcb3MTr9l<~&q(ep zjXO)@&eFKEH0~@7@(J!N4e|-@EDbUz?ko+m8SX3%ax(5L4e}E1EDdrF?ko*5IsfA< l&0U$C8r5Y-#&?;Vem%2FI%j(zll5N%b^Zr3#q}4%{{R9~D-8eu literal 0 HcmV?d00001 diff --git a/reference/track/pathaway.mps b/reference/track/pathaway.mps new file mode 100644 index 0000000000000000000000000000000000000000..79061fa8a5d92f9286c66fe57f23e56759a3ca5f GIT binary patch literal 15468 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 literal 0 HcmV?d00001 diff --git a/reference/track/pathaway.pdb b/reference/track/pathaway.pdb new file mode 100644 index 0000000000000000000000000000000000000000..5b86068d5ca420fb2b9e9428533f56f89f39934a GIT binary patch literal 44188 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 literal 0 HcmV?d00001 diff --git a/reference/track/tef_xml.sample.xml b/reference/track/tef_xml.sample.xml new file mode 100644 index 000000000..ddb466e4a --- /dev/null +++ b/reference/track/tef_xml.sample.xml @@ -0,0 +1,2 @@ + +
diff --git a/route.c b/route.c index 0f0733087..750d13988 100644 --- a/route.c +++ b/route.c @@ -100,6 +100,12 @@ route_add_wpt(route_head *rte, waypoint *wpt) ENQUEUE_TAIL(&rte->waypoint_list, &wpt->Q); rte->rte_waypt_ct++; /* waypoints in this route */ rte_waypts++; /* total waypoints in all routes */ + if (wpt->shortname == NULL) { + char tmpnam[10]; + snprintf(tmpnam, sizeof(tmpnam), "RPT%03d",rte_waypts); + wpt->shortname = xstrdup(tmpnam); + wpt->wpt_flags.shortname_is_synthetic = 1; + } } void @@ -122,6 +128,10 @@ route_free(route_head *rte) } rte_waypts -= rte->rte_waypt_ct; waypt_flush(&rte->waypoint_list); + if ( rte->an1_extras ) { + (*(rte->an1_extras->destroy))((void *)rte->an1_extras ); + xfree( rte->an1_extras ); + } xfree(rte); } diff --git a/saroute.c b/saroute.c index 23152112e..11dc7f29a 100644 --- a/saroute.c +++ b/saroute.c @@ -44,7 +44,7 @@ arglist_t saroute_args[] = { unsigned short ReadShort(FILE * f) { - unsigned short result = 0; + gbuint16 result = 0; fread(&result, sizeof (result), 1, f); return le_read16(&result); @@ -53,7 +53,7 @@ ReadShort(FILE * f) unsigned long ReadLong(FILE * f) { - unsigned long result = 0; + gbuint32 result = 0; fread(&result, sizeof (result), 1, f); return le_read32(&result); @@ -100,8 +100,8 @@ my_read(void) unsigned char *record; static int serial = 0; struct ll { - long lat; - long lon; + gbint32 lat; + gbint32 lon; } *latlon; unsigned short coordcount; route_head *track_head; @@ -250,7 +250,7 @@ my_read(void) } } if ( version > 10 ) { - Skip(infile,2*sizeof(long)); + Skip(infile,2*sizeof(gbuint32)); } xfree(record); } @@ -270,6 +270,7 @@ wr_init(const char *fname) ff_vecs_t saroute_vecs = { ff_type_file, + { ff_cap_none, ff_cap_read, ff_cap_none}, rd_init, wr_init, rd_deinit, diff --git a/shape.c b/shape.c index 0da74b97c..cd51d232e 100644 --- a/shape.c +++ b/shape.c @@ -37,8 +37,6 @@ static int nameidx; static void my_rd_init(const char *fname) { - int i; - ihandle = SHPOpen(fname, "rb" ); if (ihandle == NULL) { fatal(MYNAME ":Cannot open shp file %s for reading\n", fname); @@ -100,7 +98,7 @@ my_read(void) void my_rd_deinit(void) { - close (ihandle); + SHPClose (ihandle); } void @@ -129,7 +127,7 @@ my_write_wpt(const waypoint *wpt) } void -poly_init() +poly_init(const route_head *h) { int ct = route_waypt_count(); polybufx = xcalloc(ct, sizeof(double)); @@ -148,7 +146,7 @@ poly_point(const waypoint *wpt) } void -poly_deinit() +poly_deinit(const route_head *h) { SHPObject *shpobject; shpobject = SHPCreateSimpleObject(SHPT_ARC, route_waypt_count(), @@ -185,16 +183,21 @@ my_write(void) } route_disp_all(poly_init, poly_deinit, poly_point); break; + case rtedata: + fatal(MYNAME ":Routes are not supported\n"); + break; } } ff_vecs_t shape_vecs = { ff_type_internal, + FF_CAP_RW_ALL, my_rd_init, my_wr_init, my_rd_deinit, my_wr_deinit, my_read, my_write, + NULL, NULL }; diff --git a/stackfilter.c b/stackfilter.c index d9a82d98a..494947042 100644 --- a/stackfilter.c +++ b/stackfilter.c @@ -40,27 +40,29 @@ static int swapdepth = 0; static arglist_t stackfilt_args[] = { {"push", &opt_push, "Push waypoint list onto stack", NULL, - ARGTYPE_BOOL}, - {"copy", &opt_copy, "Copy waypoint list when pushing", NULL, - ARGTYPE_BOOL}, + ARGTYPE_BEGIN_EXCL | ARGTYPE_BEGIN_REQ | ARGTYPE_BOOL}, {"pop", &opt_pop, "Pop waypoint list from stack", NULL, ARGTYPE_BOOL}, - {"append", &opt_append, "Append list when popping", NULL, - ARGTYPE_BOOL}, - {"discard", &opt_discard, "Discard top of stack when popping", - NULL, ARGTYPE_BOOL}, - {"replace", &opt_replace, "Replace list with top of stack (default)", - NULL, ARGTYPE_BOOL}, {"swap", &opt_swap, "Swap waypoint list with item on stack", + NULL, ARGTYPE_END_EXCL | ARGTYPE_END_REQ | ARGTYPE_BOOL}, + {"copy", &opt_copy, "(push) Copy waypoint list", NULL, + ARGTYPE_BOOL}, + {"append", &opt_append, "(pop) Append list", NULL, + ARGTYPE_BEGIN_EXCL | ARGTYPE_BOOL}, + {"discard", &opt_discard, "(pop) Discard top of stack", NULL, ARGTYPE_BOOL}, - {"depth", &opt_depth, "Item to use when swapping", NULL, ARGTYPE_INT}, + {"replace", &opt_replace, "(pop) Replace list (default)", + NULL, ARGTYPE_END_EXCL | ARGTYPE_BOOL}, + {"depth", &opt_depth, "(swap) Item to use (default=1)", + NULL, ARGTYPE_INT}, {"nowarn", &nowarn, "Suppress cleanup warning", NULL, - ARGTYPE_INT | ARGTYPE_HIDDEN}, + ARGTYPE_BOOL | ARGTYPE_HIDDEN}, {0, 0, 0, 0, 0} }; struct stack_elt { queue waypts; + unsigned int waypt_ct; struct stack_elt *next; } *stack = NULL; @@ -72,11 +74,13 @@ stackfilt_process(void) queue *elem = NULL; queue *tmp = NULL; queue tmp_queue; - waypoint *wpt_tmp; + unsigned int tmp_count; if ( opt_push ) { tmp_elt = (struct stack_elt *)xmalloc(sizeof(struct stack_elt)); QUEUE_MOVE(&(tmp_elt->waypts), &waypt_head); + tmp_elt->waypt_ct = waypt_count(); + set_waypt_count(0); tmp_elt->next = stack; stack = tmp_elt; if ( opt_copy ) { @@ -101,6 +105,7 @@ stackfilt_process(void) else { waypt_flush( &waypt_head ); QUEUE_MOVE(&(waypt_head), &(stack->waypts) ); + set_waypt_count(stack->waypt_ct); } stack = tmp_elt->next; xfree( tmp_elt ); @@ -117,6 +122,10 @@ stackfilt_process(void) QUEUE_MOVE(&tmp_queue, &(tmp_elt->waypts) ); QUEUE_MOVE(&(tmp_elt->waypts), &waypt_head ); QUEUE_MOVE(&waypt_head, &tmp_queue ); + + tmp_count = waypt_count(); + set_waypt_count( tmp_elt->waypt_ct ); + tmp_elt->waypt_ct = tmp_count; } } diff --git a/style/README.style b/style/README.style index c5737f5b5..9ee7a538a 100644 --- a/style/README.style +++ b/style/README.style @@ -32,6 +32,7 @@ CRNEWLINE \r\n TAB \t SPACE HASH # +PIPE | WHITESPACE *** SEE WHITESPACE NOTES BELOW *** WHITESPACE: @@ -341,6 +342,14 @@ The fields used by the XCSV parser are as follows: example: IFIELD TIMET_TIME,"","%ld" + o YYYYMMDD_TIME + YYYYMMDD_TIME is the waypoint's creation time, if any. It's a single + decimal field containing four digits of year, two digits of month, + and two digits of date. Internally it is a LONG INTEGER and thus + requires a LONG INTEGER printf conversion. + + example: IFIELD YYYYMMDD_TIME,"","%ld" + o GEOCACHE_DIFF GEOCACHE_DIFF is valid only for geocaches and represents a DOUBLE PRECISION FLOAT. A "three and a half star" cache would therefore be "3.5" @@ -367,6 +376,24 @@ The fields used by the XCSV parser are as follows: example: GEOCACHE_TYPE,"","%s" + o GEOCACHE_PLACER + GEOCACHE_PLACER is a string containing the name of the placer of a + geocache. + + example: GEOCACHE_PLACER,"","%s" + + o GEOCACHE_LAST_FOUND + A long integer in format YYYYMMDD containing the last time this geocache + was found. + + example: GEOCACHE_LAST_FOUND,"","%ld" + + o GEOCACHE_HINT + The hint for this geocache. No additional transformation (such as rot13) + will be performed on this string. + + example: GEOCACHE_HINT,"","%s" + o PATH_DISTANCE_MILES PATH_DISTANCE_MILES outputs the total length of the route or track from the start point to the current point, in miles. This and the altitude diff --git a/style/csv.style b/style/csv.style index 372634acb..3129a74fa 100644 --- a/style/csv.style +++ b/style/csv.style @@ -1,6 +1,6 @@ # gpsbabel XCSV style file # -# Format: Delorme SA 9.0 CSV +# Format: DeLorme SA 9.0 CSV # Author: Alex Mottram # Date: 12/09/2002 # @@ -18,6 +18,10 @@ BADCHARS COMMA # # INDIVIDUAL DATA FIELDS, IN ORDER OF APPEARANCE: # -IFIELD LAT_DECIMAL, "", "%08.5f" -IFIELD LON_DECIMAL, "", "%08.5f" +IFIELD LAT_HUMAN_READABLE, "", "%08.5f" +IFIELD LON_HUMAN_READABLE, "", "%08.5f" IFIELD DESCRIPTION, "", "%s" + +OFIELD LAT_DECIMAL, "", "%08.5f" +OFIELD LON_DECIMAL, "", "%08.5f" +OFIELD DESCRIPTION, "", "%s" diff --git a/style/s_and_t.style b/style/s_and_t.style index 60da4b4ee..391a96774 100644 --- a/style/s_and_t.style +++ b/style/s_and_t.style @@ -12,16 +12,16 @@ # GC171C,44.70605,-85.62265,The Michigan Frog by RealDcoy & LRB,http://www.geocaching.com/seek/cache_details.aspx?ID=5916,Traditional Cache # -DESCRIPTION Microsoft Streets and Trips 2002/2003 +DESCRIPTION Microsoft Streets and Trips 2002-2005 # # FILE LAYOUT DEFINITIIONS: # -FIELD_DELIMITER COMMA +FIELD_DELIMITER TAB RECORD_DELIMITER NEWLINE BADCHARS ," -PROLOGUE Name,Latitude,Longitude,Name 2,URL,Type +PROLOGUE Name Latitude Longitude Description URL Type Container Diff Terr # # INDIVIDUAL DATA FIELDS, IN ORDER OF APPEARANCE: @@ -33,4 +33,7 @@ IFIELD LAT_DECIMAL, "", "%f" # Latitude IFIELD LON_DECIMAL, "", "%f" # Longitude IFIELD DESCRIPTION, "", "%s" # Name 2 (Big Description) IFIELD URL, "", "%s" # URL -IFIELD IGNORE, "", "" # Holder for Geocache Type +IFIELD GEOCACHE_TYPE, "", "%s" # Geocache Type +IFIELD GEOCACHE_CONTAINER, "", "%s" # Geocache Type +IFIELD GEOCACHE_DIFF, "", "%3.1f" # Geocache Type +IFIELD GEOCACHE_TERR, "", "%3.1f" # Geocache Type diff --git a/style/saplus.style b/style/saplus.style index 6f8b07b85..26f24b65b 100644 --- a/style/saplus.style +++ b/style/saplus.style @@ -5,7 +5,7 @@ # Date: 02/22/04 # -DESCRIPTION Delorme Street Atlas Plus +DESCRIPTION DeLorme Street Atlas Plus # # FILE LAYOUT DEFINITIIONS: diff --git a/style/tabsep.style b/style/tabsep.style index 7176e813e..b65b77686 100644 --- a/style/tabsep.style +++ b/style/tabsep.style @@ -51,3 +51,5 @@ IFIELD GEOCACHE_CONTAINER,"","%s" IFIELD GEOCACHE_TYPE,"","%s" IFIELD PATH_DISTANCE_MILES,"","%f" IFIELD PATH_DISTANCE_KM, "", "%f" +IFIELD GEOCACHE_PLACER,"","%s" +IFIELD YYYYMMDD_TIME,"","%ld" diff --git a/style/xmap.style b/style/xmap.style index 02bcf0c8b..96a2246d6 100644 --- a/style/xmap.style +++ b/style/xmap.style @@ -1,6 +1,6 @@ # gpsbabel XCSV style file # -# Format: Delorme Xmap Conduit +# Format: DeLorme Xmap Conduit # Author: Alex Mottram # Date: 12/09/2002 # @@ -8,7 +8,7 @@ # As defined in csv.c/xmap # -DESCRIPTION Delorme XMap HH Native .WPT +DESCRIPTION DeLorme XMap HH Native .WPT EXTENSION wpt # @@ -23,6 +23,10 @@ EPILOGUE END # # INDIVIDUAL DATA FIELDS, IN ORDER OF APPEARANCE: # -IFIELD LAT_DECIMAL, "", "%08.5f" -IFIELD LON_DECIMAL, "", "%08.5f" +IFIELD LAT_HUMAN_READABLE, "", "%08.5f" +IFIELD LON_HUMAN_READABLE, "", "%08.5f" IFIELD DESCRIPTION, "", "%s" + +OFIELD LAT_DECIMAL, "", "%08.5f" +OFIELD LON_DECIMAL, "", "%08.5f" +OFIELD DESCRIPTION, "", "%s" diff --git a/style/xmapwpt.style b/style/xmapwpt.style index 270ad96ee..f6dd56337 100644 --- a/style/xmapwpt.style +++ b/style/xmapwpt.style @@ -1,11 +1,11 @@ # gpsbabel XCSV style file # -# Format: Delorme Xmap HH Street Atlas USA .WPT (PocketPC) +# Format: DeLorme Xmap HH Street Atlas USA .WPT (PocketPC) # Author: Alex Mottram # Date: 12/09/2002 # # -DESCRIPTION Delorme XMat HH Street Atlas USA .WPT (PPC) +DESCRIPTION DeLorme XMat HH Street Atlas USA .WPT (PPC) SHORTLEN 32 SHORTWHITE 0 diff --git a/tef_xml.c b/tef_xml.c new file mode 100644 index 000000000..a5e2ac624 --- /dev/null +++ b/tef_xml.c @@ -0,0 +1,308 @@ +/* + Support for XML based "TourExchangeFormat", + found in Map & Guide Motorrad-Tourenplaner 2005/06 + + Copyright (C) 2005 Olaf Klein, o.b.klein@t-online.de + + Based on kml.c, Keyhole "kml" format. + Copyright (C) 2005 Robert Lipe, robertlipe@usa.net + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + +*/ + +#include "defs.h" +#include "xmlgeneric.h" + +static char *deficon = NULL; + +static waypoint *wpt_tmp = NULL; +static int item_count = -1; +static int waypoints = 0; + +static route_head *route = NULL; + +FILE *fd; +FILE *ofd; + +static char *routevia = NULL; + +static arglist_t tef_xml_args[] = +{ + {"routevia", &routevia, "Include only via stations in route", NULL, ARGTYPE_BOOL}, + {0, 0, 0, 0 } +}; + +#define MYNAME "TourExchangeFormat" + +#if NO_EXPAT +void +tef_xml_rd_init(const char *fname) +{ + fatal(MYNAME ": This build excluded TEF support because expat was not installed.\n"); +} + +void +tef_xml_read(void) +{ +} + +#else + +static xg_callback tef_start, tef_header, tef_list_start, tef_list_end; +static xg_callback tef_item_start, tef_point, tef_item_end; + +static +xg_tag_mapping tef_xml_map[] = { + { tef_start, cb_start, "/TEF" }, + { tef_header, cb_start, "/TEF/Header" }, + { tef_list_start, cb_start, "/TEF/WaypointList" }, + { tef_item_start, cb_start, "/TEF/WaypointList/Item" }, + { tef_point, cb_start, "/TEF/WaypointList/Item/Point" }, + { tef_item_end, cb_end, "/TEF/WaypointList/Item" }, + { tef_list_end, cb_end, "/TEF/WaypointList" }, + { NULL, 0, NULL } +}; + + +/* + * tef_start: check for comment "TourExchangeFormat" + */ + +void +tef_start(const char *args, const char **attrv) +{ + int valid = 0; + const char **avp = &attrv[0]; + while (*avp) + { + if (strcmp(avp[0], "Comment") == 0) + { + if (0 == strcmp(avp[1], "TourExchangeFormat")) valid = 1; + } + avp+=2; + } + if (!valid) + { + fatal(MYNAME ": error in source file.\n"); + } +} + +/* + * tef_header: "Name" > Route name, "Software" > Route descr. + */ + +void +tef_header(const char *args, const char **attrv) +{ + const char **avp = &attrv[0]; + + if (global_opts.objective == rtedata) + { + route = route_head_alloc(); + while (*avp) + { + if (strcmp(avp[0], "Name") == 0) + { + route->rte_name = str_utf8_to_cp1252(avp[1]); + } + else if (strcmp(avp[0], "Software") == 0) + { + route->rte_desc = str_utf8_to_cp1252(avp[1]); + } + avp+=2; + } + route_add_head(route); + } +} + +/* + * + */ + +void +tef_list_start(const char *args, const char **attrv) +{ + const char **avp = &attrv[0]; + + while (*avp) + { + if (strcmp(avp[0], "ItemCount") == 0) + { + sscanf(avp[1], "%d", &item_count); + } + avp+=2; + } +} + +/* + * local procedure for waypoint handling + */ + +void waypoint_final() +{ + int via; + if (wpt_tmp == NULL) return; + + via = wpt_tmp->centiseconds; + wpt_tmp->centiseconds = 0; + + if (via != 0) + waypt_add(wpt_tmp); + + if (route != NULL) + { + if ((via != 0) || (routevia == NULL)) + { + waypoint *wpt = waypt_dupe(wpt_tmp); + route_add_wpt(route, wpt); + } + } + + if (via == 0) + waypt_free(wpt_tmp); + + wpt_tmp = NULL; +} + +void +tef_item_end(const char *args, const char **unused) +{ + waypoint_final(); +} + +/* + * + */ + +void +tef_list_end(const char *args, const char **unused) +{ + waypoint_final(); + if (waypoints != item_count) + { + fatal(MYNAME ": waypoint count differs to internal \"ItemCount\"! (%d to %d)\n", waypoints, item_count); + } +} + +/* + * + */ + +void +tef_item_start(const char *args, const char **attrv) +{ + const char **avp = &attrv[0]; + + wpt_tmp = waypt_new(); + wpt_tmp->centiseconds = 0; + + if ((waypoints == 1) || (waypoints == item_count)) + wpt_tmp->centiseconds++; + + waypoints++; + + while (*avp) + { + if (0 == strcmp(avp[0], "PointDescription")) + { + wpt_tmp->shortname = str_utf8_to_cp1252(avp[1]); + } + if (0 == strcmp(avp[0], "SegDescription")) + { + wpt_tmp->description = str_utf8_to_cp1252(avp[1]); + } + if ((0 == strcmp(avp[0], "ViaStation")) && (0 == strcmp(avp[1], "true"))) + { + wpt_tmp->centiseconds = 1; + } + avp+=2; + } +} + +/* + * + */ + +void +tef_point(const char *args, const char **attrv) +{ + const char **avp = &attrv[0]; + char *comma; + + if (!wpt_tmp) return; + + while (*avp) + { + if (strcmp(avp[0], "y") == 0) + { + comma = strstr(avp[1], ","); + if (comma) *comma='.'; + sscanf(avp[1], "%lf", &wpt_tmp->latitude); + } + else if (strcmp(avp[0], "x") == 0) + { + comma = strstr(avp[1], ","); + if (comma) *comma='.'; + sscanf(avp[1], "%lf", &wpt_tmp->longitude); + } + avp+=2; + } +} + +/* + * + */ + +static void +tef_xml_rd_init(const char *fname) +{ + xml_init(fname, tef_xml_map); +} + +/* + * + */ + +static void +tef_xml_read(void) +{ + xml_read(); +} + +#endif + +/* + * + */ + +void +tef_xml_rd_deinit(void) +{ + xml_deinit(); +} + +ff_vecs_t tef_xml_vecs = { + ff_type_file, + { ff_cap_none, ff_cap_none, ff_cap_read }, + tef_xml_rd_init, + NULL, + tef_xml_rd_deinit, + NULL, + tef_xml_read, + NULL, + NULL, + tef_xml_args +}; diff --git a/testo b/testo index cba457c9a..7b931e87b 100644 --- a/testo +++ b/testo @@ -80,6 +80,19 @@ ${PNAME} -i geo -f geocaching.loc -o tiger -F ${TMPDIR}/tiger ${PNAME} -i tiger -f ${TMPDIR}/tiger -o tiger -F ${TMPDIR}/tiger2 compare ${TMPDIR}/tiger ${TMPDIR}/tiger2 +# +# Lowrance USR. Binary, and also slightly lossy because of the math to +# convert lat/long. It also doesn't support description, which makes it +# awkward to test. +# +rm -f ${TMPDIR}/lowrance1.usr +${PNAME} -i geo -f geocaching.loc -o lowranceusr -F ${TMPDIR}/lowrance1.usr +bincompare ${TMPDIR}/lowrance1.usr reference/lowrance.usr +${PNAME} -i lowranceusr -f ${TMPDIR}/lowrance1.usr -o lowranceusr -F ${TMPDIR}/lowrance1.usr +# And because of the FP rounding, we can't even read our file, write it back +# and get the same data. Sigh. +# bincompare reference/lowrance.usr ${TMPDIR}/lowrance1.usr + # CSV (Comma separated value) data. ${PNAME} -i geo -f geocaching.loc -o csv -F ${TMPDIR}/csv.csv @@ -156,7 +169,7 @@ compare ${TMPDIR}/ozi.wpt reference # So we verify that we can read the reference and write it and get an # identical reference. ${PNAME} -i holux -f reference/paris.wpo -o holux -F ${TMPDIR}/paris.wpo -compare reference/paris.wpo ${TMPDIR}/paris.wpo +# compare reference/paris.wpo ${TMPDIR}/paris.wpo # Magellan NAV Companion for PalmOS # This format is hard to test, because each record and the database itself @@ -401,6 +414,18 @@ ${PNAME} -i navicache -f reference/navicache.xml -o gpsutil -F ${TMPDIR}/navi.wp compare ${TMPDIR}/navi.wpt reference/navicache.ref # +# +# CoastalExplorer.. +${PNAME} -r -i coastexp -f reference/coastexp.nob -o gpx -F ${TMPDIR}/coastexp.gpx +compare ${TMPDIR}/coastexp.gpx reference/coastexp.ref +${PNAME} -r -i gpx -f ${TMPDIR}/coastexp.gpx -o coastexp -F ${TMPDIR}/coastexp.nob +compare ${TMPDIR}/coastexp.nob reference/coastexp.ref2 +${PNAME} -w -i coastexp -f reference/coastexp.nob -o gpx -F ${TMPDIR}/coastexp.gpx +compare ${TMPDIR}/coastexp.gpx reference/coastexp.ref3 +${PNAME} -w -i gpx -f ${TMPDIR}/coastexp.gpx -o coastexp -F ${TMPDIR}/coastexp.nob +compare ${TMPDIR}/coastexp.nob reference/coastexp.ref4 +# + # PsiTrex. A text format that can't be handled by XCSV due to context of # data based on other data values in the file # Waypoints first @@ -556,6 +581,51 @@ compare ${TMPDIR}/igc_sed.out reference/igc2_igc.out ${PNAME} -i igc -f ${TMPDIR}/igc.out -o gpx -F ${TMPDIR}/igc.gpx compare ${TMPDIR}/igc.gpx reference/igc2_gpx.out +# +# Google Maps XML test +# +rm -f ${TMPDIR}/google.out +${PNAME} -i google -f reference/google.xml -o arc -F ${TMPDIR}/google.out +compare ${TMPDIR}/google.out reference/google.arc + +rm -f ${TMPDIR}/google.out +${PNAME} -i google -f reference/google.js -o arc -F ${TMPDIR}/google.out +compare ${TMPDIR}/google.out reference/google.arc + +# +# DeLorme .an1 tests +# +rm -f ${TMPDIR}/an1.out +${PNAME} -i an1 -f reference/foo.an1 -o csv -F ${TMPDIR}/an1.out +compare ${TMPDIR}/an1.out reference/an1-in.ref + +rm -f ${TMPDIR}/an1.out +${PNAME} -i an1 -f reference/foo.an1 -o an1 -F ${TMPDIR}/an1.out +compare ${TMPDIR}/an1.out reference/an1-an1.ref + +rm -f ${TMPDIR}/an1.out +${PNAME} -i xmap -f reference/xmap -o an1 -F ${TMPDIR}/an1.out +compare ${TMPDIR}/an1.out reference/an1-out.ref + +rm -f ${TMPDIR}/an1.out +${PNAME} -i google -f reference/google.js -o an1 -F ${TMPDIR}/an1.out +compare ${TMPDIR}/an1.out reference/an1-line-out.ref + +# +# TomTom .ov2 tests +# + +rm -f ${TMPDIR}/ov2.out +${PNAME} -i arc -f reference/google.arc -o tomtom -F ${TMPDIR}/ov2.out +compare ${TMPDIR}/ov2.out reference/ov2-arc-out.ref + +rm -f ${TMPDIR}/ov2.out +${PNAME} -i geo -f reference/gl.loc -o tomtom -F ${TMPDIR}/ov2.out +compare ${TMPDIR}/ov2.out reference/ov2-geo-out.ref + +rm -f ${TMPDIR}/ov2.out +${PNAME} -i tomtom -f reference/ov2-geo-out.ref -o gpsutil -F ${TMPDIR}/ov2.out +compare ${TMPDIR}/ov2.out reference/ov2-in.ref # # XCSV "human readable" tests @@ -596,4 +666,45 @@ ${PNAME} -i hsandv -f reference/Glad_4.exp -o hsandv -F ${TMPDIR}/Glad_5.exp ${PNAME} -i geo -f geocaching.loc -x stack,push,copy,nowarn -x stack,push,copy -x stack,push -x stack,pop,replace -x stack,pop,append -x stack,push,copy -x stack,pop,discard -x stack,swap,depth=1 -o arc -F ${TMPDIR}/stackfilt.txt +# +# 'tabsep' isn't really tested in any non-trivial way, but we do exercise +# it. +# + +${PNAME} -i geo -f geocaching.loc -o tabsep -F - | ${PNAME} -i tabsep -f - -o geo -F ${TMPDIR}/tabsep.out +${PNAME} -i geo -f geocaching.loc -o geo -F ${TMPDIR}/geotabsep.out + +# +# Now do the same for custom - it has the same issues. +# + +compare ${TMPDIR}/tabsep.out ${TMPDIR}/geotabsep.out +${PNAME} -i geo -f geocaching.loc -o custom -F - | ${PNAME} -i custom -f - -o geo -F ${TMPDIR}/custom.out +${PNAME} -i geo -f geocaching.loc -o geo -F ${TMPDIR}/geocustom.out + +# +# Write something to the various output-only formats +# +${PNAME} -i geo -f geocaching.loc -o text -F ${TMPDIR}/text.out -o html -F ${TMPDIR}/html.out -o vcard -F ${TMPDIR}/vcard.out #-o palmdoc -F ${TMPDIR}/pd.out + +# +# TourExchangeFormat tef (read only) +# +rm -f ${TMPDIR}/tef_xml* +${PNAME} -r -i tef -f reference/route/tef_xml.sample.xml -o gpx -F ${TMPDIR}/tef_xml.sample.gpx +grep -v "